6 ms·
Common Lisp Elitism is a real thing. This person appears to be from the "Clojure is not Lisp" clan of gatekeepers.
by divs1210 6y ago
Common Lisp Elitism is a real thing. This person appears to be from the "Clojure is not Lisp" clan of gatekeepers.
- fulafel 6y agoI think the characterisation of Clojure is not that unfair here. It's Clojure keywords have the role that Lisp's symbols have (and I think they have better ergonomics), and symbols are mostly only used for source code representation. In other Lisps the detailed semantics of symbols are more important including the identity/interning thing. Rich Hickey was a Common Lisp user before making Clojure so there's a fair chance he knew how symbols worked there, so the cargo culting characterisation should be applied only light heartedly :)
- reitzensteinm 6y agoThat Clojure is keyword heavy is true, but it's so important to note that objects are essentially never checked for reference equality in Clojure, even when e.g. looking up keys in a hash map (see demo). With this is mind, you could stop interning keywords and damn near every Clojure program would continue to work just fine - but with a noticeable slowdown. Or, more sensibly and to bring it back to the theme of the thread, for adding a second non-interning Keyword type which can safely be generated while deserializing user input in a long running process, that you can use interchangeably with standard keywords, but will be garbage collected away with the reset of the deserialized data when you're done. You do pay a hefty penalty here because you're hiding everything behind interfaces and abstractions. It's totally fine to not like the system, or believe it's not worth the performance hit. But it does mean that a potentially equal but not identical symbol isn't some off brand low quality replacement as GP suggests, it's just... a symbol. Pastebin demo: https://pastebin.com/cbWiNyEL https://pastebin.com/cbWiNyEL
- fulafel 6y agoGood points. It's interesting that despite this keywords are serialized all the time in Clojure land (eg in the transit format that is commonly used for frontend/backend communication).
- reitzensteinm 6y agoI think Google's warning definitely applies to Clojure. Most json libraries will convert string keys to keywords, and they're not weak references. An attacker can probably just send a few dozen gigabytes of random json to the average Clojure app and it's going to go down.
- kazinator 6y agoI wouldn't write a config file parsing library for C programs without interning, so == between two pointers could be used to test for keyword equality. Interning is used outside of LIsp. See the XInternAtom function in the X Window system: Atom XInternAtom( Display *display, char *atom_name, Bool only_if_exists ); or RegisterClass in Win32: ATOM RegisterClassA( const WNDCLASSA *lpWndClass );
- reitzensteinm 6y agoI wouldn't either :)
- lispm 6y agoFor Lisp the following is the usual behavior: Symbols are by default interned and identical symbols are tested with EQ to be T. > (eq (read) (read)) a a T The default test function is EQL, which is using EQ to test symbols. In Common Lisp #:a would be an uninterned symbol with the name "A". > (find 'a '(#:a a)) A > (find 'a '(#:a a) :test #'string-equal) #:A setting the value of a symbol will basically work in all Lisps with symbols in similar fashion like this: > (dolist (item '(a b c a)) (set item (if (and (boundp item) (numberp (eval item))) (1+ (eval item)) 1))) NIL > (mapcar 'eval '(a b c a)) (2 1 1 2) This last example will for example run unchanged in Emacs Lisp and Common Lisp.
- reitzensteinm 6y agoWhat is the purpose of creating uninterned symbols?
- lispm 6y agoThey could be used as symbols which can be GCed. Though a typical use is in macros, where macros introduce new symbols and these should never clash with any existing symbol and to which there should be no access via the name. Example: A macro which writes the form, the value and which returns the value. GENSYM generates a named/counted uninterned symbol. > (defmacro debugit (form &aux (value-symbol (gensym "value"))) `(let ((,value-symbol ,form)) (format t "~%The value of ~a is ~a~%" ',form ,value-symbol) ,value-symbol)) DEBUGIT If we look at the expanded code of an example, we can see uninterned symbols: > (pprint (macroexpand-1 '(debugit (sin pi)))) (LET ((#:|value1093| (SIN PI))) (FORMAT T "~%The value of ~a is ~a~%" '(SIN PI) #:|value1093|) #:|value1093|) We can also let the printer show us the identities of these symbols, labelling objects which are used multiple times in an s-expression: > (setf *print-circle* t) T > (pprint (macroexpand-1 '(debugit (sin pi)))) (LET ((#2=#:|value1095| #1=(SIN PI))) (FORMAT T "~%The value of ~a is ~a~%" '#1# #2#) #2#) Thus we can see above that it's just one uninterned symbol used in three places. Example run: > (debugit (sin pi)) The value of (SIN PI) is 1.2246063538223773D-16 1.2246063538223773D-16
- deleted 6y ago[deleted]
- kazinator 6y agoI thought I was one of these gatekeepers; and that was before I found out that Clojure doesn't actually have symbols, but just a string type with a quote-free read syntax. Even AutoCAD's AutoLisp (the old one from the 1980's) has interned symbols. How symbols work goes back all the way to the original MacCarthy work, and all of its actual (not cargo-culted) descendants. It is not "Common Lisp" elitism.
- reitzensteinm 6y agoFor what it's worth, I agree with you. Clojure only weakly holds on to its lisp heritage. I'd liken it to the similarity between C# and C++ (without implying any superiority to either side). Superficially quite similar, some parts near identical, others a complete detour. With that in mind, however, basing your critique of Clojure on the extent to which it carries the lisp tradition is bizarre. Your criticisms are born of an ignorance of the value proposition Clojure provides, which would not be terribly different even if it had eschewed lisp syntax in favor of something else. If you actually learned Clojure, there is zero chance you'd be complaining about symbol interning. It's just so ridiculous. You'd probably still think the whole thing is a waste of time, and I'm sure you'd have a big long list of actual, meaningful complaints. I've seen people criticize TXR for its ugly syntax once or twice here on HN (I pay close attention to lisp posts here), and I thought that was dumb at the time. I'm not interested in learning it but I'm glad you're trying something new. It's a shame to see you stoop to the same level of drive by dismissal. But whatever. Let's flip each other's bozo bits and move on.
- kazinator 6y agoI mentioned AutoLISP to make it clear that the comment is completely unrelated to value proposition, but in hindsight, that may be too obscure.
- reitzensteinm 6y agoYou call Clojure a cargo cult descendant, which implies it's failing to achieve what its ancestors did, by copying features haphazardly without understanding the deeper motivations behind them. Clojure is a shitty substitute for CL, but that's just not what it is trying to be. It is an interesting and worthy system in its own right.
- lispm 6y agoalmost every language which has Lisp in its name is using some form of symbol tables for interning, from McCarthy's Lisp 1 implementation onwards. That's one of the defining features of the Lisp s-expression reader. If the 'reader' reads an s-expression like (EMACS LISP IS A LISP DIALECT) then both occurrences of LISP are the same identical Lisp object, both are the same symbol. If your language is doing something different, then it's not using symbols like Lisp-like languages usually do since the dawn of time.