Nah, I just do
{:color “brown” :name “fred”} {:color “brown” :name “fred”} CL-USER> (set-macro-character #\{
(lambda (str char)
(declare (ignore char))
(let ((*readtable* (copy-readtable *readtable* nil))
(keep-going t))
(set-macro-character #\} (lambda (stream char)
(declare (ignore char) (ignore stream))
(setf keep-going nil)))
(let ((pairs (loop for key = (read str nil nil t)
while keep-going
for value = (read str nil nil t)
collect (list key value)))
(retn (gensym)))
`(let ((,retn (make-hash-table :test #'equal)))
,@(mapcar
(lambda (pair)
`(setf (gethash ,(car pair) ,retn) ,(cadr pair)))
pairs)
,retn)))))
T
CL-USER> {:foo 100500 :bar 42}
#<HASH-TABLE :TEST EQUAL :COUNT 2 {1005879463}>
CL-USER> (alexandria:hash-table-alist #v1)
((:BAR . 42) (:FOO . 100500))
CL-USER>
And define a printer for the hash to output it as desired: CL-USER> (defmethod print-object ((obj hash-table) stream)
(princ "{" stream)
(loop with indent = nil
for key being the hash-keys in obj using (hash-value value)
when indent
do (format stream "~% ")
unless indent
do (setf indent t)
do (format stream "~S ~S" key value))
(princ "}" stream))
#<STANDARD-METHOD COMMON-LISP:PRINT-OBJECT (HASH-TABLE T) {10040C9F83}>
CL-USER> {:foo 100500 :bar 42}
{:FOO 100500
:BAR 42} (defparameter a '((color brown)
(name fred)))But you could do:
(def foo {:color "brown" :name "fred"})
Anytime you want to get the color out you can just call the :color function and pass the map (:color foo)
=> "brown"
(:name foo)
=> "fred"
Likewise, we can call the map as the function and pass the key as the argument (foo :name)
=> "fred"
We also have nice ways to destructure and bind values in maps when passed as parameters to functions (defn my-func [{:keys [color name]}]
(println "Color: " color)
(println "Name: " name))
(my-func foo)
=>
Color: brown
Name: fred