5 ms·
honest question: is the following the way you do hashmaps in lisp: ? ``` (setq a (make-hash-table)) (setf (gethash 'color a) 'brown) (setf (gethash 'name a)
by singularity2001 7y ago
honest question: is the following the way you do hashmaps in lisp: ?
```
(setq a (make-hash-table))
(setf (gethash 'color a) 'brown)
(setf (gethash 'name a) 'fred)
(gethash 'color a) => brown
(gethash 'name a) => fred
(gethash 'pointy a) => nil
```
vs
```
a = {
color:'brown',
name:'fred'
}
```
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- dreamcompiler 7y agoYes, that's the lowest-level API. But if you have a lot of hashmaps to specify literally, you could create a DSL for them as follows: (defparameter a '((color brown) (name fred))) (defun make-hashmap (pairs) (let ((ht (make-hash-table))) (mapc (lambda (pair) (setf (gethash (car pair) ht) (cadr pair))) pairs) ht)) (defun showhash (hash-table) "Show hash-table" (maphash #'(lambda (key value) (format t "~%~S : ~S" key value)) hash-table)) (showhash (make-hashmap a))
- fiddlerwoaroof 7y agoOr you can use reader macros (or normal macros) like fset does: https://fwoar.co/pastebin/d281bd93810a1f9491ec42080ea222af80077490.nil.html https://fwoar.co/pastebin/d281bd93810a1f9491ec42080ea222af80...
- dreamcompiler 7y agoIn principle I agree that reader macros are handy. In practice I mostly avoid them because reader macros don't have separate namespaces in CL, so it's likely your reader macro will step on one from an external library. (Yes, you can carefully bind *readtable* before compiling code, but methods for doing so are ad hoc and not standardized. This is a perfect example of a convention that Common Lisp programmers need to establish formally when using CL for software engineering.)
- fiddlerwoaroof 7y agoThis problem is mostly solved with named-readtables: You declare a readtable like this: https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/master/readtable.lisp#L24 https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/mast... And use it like this: https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/master/objc-data-extractors.lisp#L16 https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/mast...
- dreamcompiler 7y agoNow that you mention it I vaguely remember this. Need to look it up again. Thanks!
- keymone 7y agoNah, I just do {:color “brown” :name “fred”}
- dreamcompiler 7y agoThat works in Clojure but not "Lisp" in general, which is what the parent asked about and for which they gave an example.
- deleted 7y ago[deleted]
- svetlyak40wt 7y agoYou can define your own syntax in CL: 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}
- singularity2001 7y ago
- deleted 7y ago[deleted]
- flavio81 7y ago>honest question: is the following the way you do hashmaps in lisp: ? >vs >a = { color:'brown', name:'fred' } For such simple data you don't need to use a hashtable in Lisp. You just do: (:color "brown" :name "fred") then you get the name using: (getf x :name) Btw, anything you can represent in JSON, you can also represent in Lisp s-expressions. But not the other way around(!) Hashtables, in Common Lisp, are intended for big amounts of data, that's why CL includes several options to tune their performance.
- dreamcompiler 7y ago> (:color "brown" :name "fred") This works, but it's a plist and thus O[n] for lookup. I assumed the questioner wanted an O[1] data structure; thus a hash table is the better answer. (Granted it makes little difference when n is small.)
- flavio81 7y ago>This works, but it's a plist and thus O[n] for lookup. I assumed the questioner wanted an O[1] data structure; thus a hash table is the better answer. (Granted it makes little difference when n is small.) There was a test on some Common Lisp implementations, of hashtables versus plists on access speeds. On small (<30?) datasets, plists were much faster than hashtables. Bigger than that, the constant access speed of hashtables makes HTs a more sane choice. The other thing is memory consumption -- on CL, plists are very frugal.