4 ms·
I like Clojure because it's a Lisp 1 and the novelty of having MVCC implemented in my language. With respect to the Lisp 1/2 debate, I hate how this: (def
by madmax96 10y ago
I like Clojure because it's a Lisp 1 and the novelty of having MVCC implemented in my language.
With respect to the Lisp 1/2 debate, I hate how this:
(defun foo (g y)
(g y))
(foo #'- 10) ; error
Is an error in Common Lisp. Instead, you have to:
(defun foo (g y)
(funcall g y))
(foo #'- 10) ; works
That's just so inelegant IMO. Scheme does the "right" thing and lets you do:
(define (foo g y) (g y))
(foo - 10) ; works
but lacks a de facto build tool and package management system. (I also really like Scheme's macro system, but not everyone agrees). Clojure solves the build tool and package management system, does the "right" thing with higher order functions, and offers seamless Java(Script) interop, which is why it has enjoyed more "mainstream" success than other Lisps.
- bitwize 10y agoR7RS has a standard package system. There seems to be some consensus on using Marc Feeley's Snow for distribution of R7RS packages. If you're running Racket, there's also PLaneT.
- lispm 10y agoBut: (define (foo lst) (list (map + lst) (map - lst))) WTF? Or: (define (foo + - lst) (+ (reduce + lst) (reduce - lst))) (foo - +)
- zeveb 10y ago> I like Clojure because it's a Lisp 1 That's one of the things I hate about Clojure. I _like_ being able to do this: (defun foo (list) (list "length" (length list)))
- madmax96 10y agoThat is convenient, but keep in mind that namespaces solve this problem: (defn foo [list] (clojure.core/list "length" (count list))) Or, in the case of CL, we could do this: (defun foo (list) (cl:list "length" (length list))) I'd argue that you should do this anyway to clarify what you mean by "list" when you shadow a common name like that.
- junke 10y ago> I'd argue that you should do this anyway to clarify what you mean by "list" when you shadow a common name like that. Absolutely not, don't encourage people to do this in CL. Clojure is Clojure, you have to do this, or if you prefer you can use use (refer ... :rename {...}) to reference external names with different local names. CL packages have their own semantic w.r.t. importing and shadowing symbols. Without context, if I read your example in CL, I am starting to ask myself if I am in a package where you defined a "list" function, because this is the unique case that requires me to explicitely qualify cl:list. If there was any confusion in the first place, I could easily select the symbol and ask Lisp what it is and whose package it belongs to.
- madmax96 10y agoReadability matters. Specifying the namespace of `list` communicates one and only one idea: I am referring to a particular binding of `list`. By leaving out the namespace qualifier when you shadow a symbol you can only add to the cognitive load necessary to understand the meaning of the code. A languages' only purpose to communicate meaning, whether that be to a machine or a person. > if I read your example in CL, I am starting to ask myself > if I am in a package where you defined a "list" function Anytime you use a shadowed symbol, qualify it with a namespace. Just because you can do something does not mean you should. It won't hurt the code and it makes the meaning perfectly clear.
- junke 10y ago> Readability matters. That's what I am telling you: in CL, your example does not make sense except in a package "FOO" where FOO:LIST is a function/macro, simply because there is absolutely no ambiguity between a function named LIST and a variable named LIST. If I am in the CL-USER package and write (LIST (LENGTH LIST)), both occurrences of LIST refer to the same symbol, and there is no "shadowing" in place in the CL sense of the term. > Specifying the namespace of `list` communicates one and only one idea: I am referring to a particular binding of `list` The fact that you prefix or not the symbol with a package has no impact on the binding, i.e. the (CL) namespace where the symbol is being looked-up. As an operator, list is bound in the function namespace (and can't be redefined). Likewise, (find-class 'list) or (gethash my-hash 'list) look for different bindings in different namespaces. What (CL:LIST LIST) actually communicates is that both symbols are most likely to be different ones, since for some reason the writer felt the need to distinguish them. That example tells me that something unusual is happening. Assuming we are in package "P": - You can refer to a symbol from another package like you did: (lib:foo bar) - or, if you don't have currently a FOO function in your package, you can (import 'lib:foo), in which case you can write: (foo bar) You may mix symbols from different packages, as long as they don't conflict, but in some cases that might be difficult to understand. Whether you qualify all of them or only a subset depends on the actual context. - Finally, if you happen to have already a FOO in your package P but you prefer to use FOO from "lib", you can shadow the first one, and so: (foo bar) ... will read as (lib:foo p:bar). But then you can't access p:foo anymore. That's why "Anytime you use a shadowed symbol, qualify it with a namespace" is a strange thing to say under the CL notion of shadowing symbols, because by definition the symbol that was shadowed is uninterned and not accessible anymore, except if you manage to keep a reference to it or store a value that was bound to it in some namespace.