6 ms·
LISP doesn't really have a hugely complex conceptual level. It gives you a list, which can be combined to form complex structures, and also a list can be code.
by ben509 7y ago
LISP doesn't really have a hugely complex conceptual level. It gives you a list, which can be combined to form complex structures, and also a list can be code.
MLs took ideas in LISP much further and imposed powerful type systems on them, so they appeal to a smaller audience than LISP does.
And the multi-paradigm languages simplified ideas from LISP to be usable for a broader audience, and brought in new ideas from elsewhere.
So I don't think SE has failed to reach LISP, if anything, it's surpassed it.
- dreamcompiler 7y ago> It gives you a list, which can be combined to form complex structures In Common Lisp, using lists for most data structures is a mark of a poor programmer. If you think Lisp is about list processing, you perhaps need to become familiar with how Lisp has evolved since the 1970s.
- singularity2001 7y agohonest 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.
- ben509 7y agoAs far as representing code the same way it represents data, that's still done with lists. And the fact that code and data have an identical representation is the most unique feature of LISP. Recall that the original claim was that software engineering hasn't caught up to LISP. Making metaprogramming trivial by using an identical presentation for code and data is the key insight of LISP, and we do a lot of metaprogramming in many languages, so yes, we've caught up with LISP.
- dreamcompiler 7y agoIt's true that "code and data have an identical representation" but the important point is that neither of those things is a string. Strings are simply one presentation of code and data, but they're not what Lisp uses internally. In most languages, this distinction is not important, but it's critical for Lisp. If SWE had caught up with Lisp, git for example would be able to produce differences in function definitions, rather than merely in the strings in files that represent those function definitions. That would make git a lot more useful to a Lisp programmer.
- discreteevent 7y agoAlso the reason why for me it's essential to use an editor (usually an IDE) that works with the AST when using other languages. But it's a good point you make. If lisp (or lua tables or any kind of tree) were the base structure for everything instead of bytes it really would be a huge jump up. (There were probably many attempts at this including Charles Simonyi s language based workbench and also in the eclipse world with EMF as the basic tree .. urbit/nock etc etc)