3 ms·
You're dangerously close to trolling, but I'll comment anyway. > a "I hate parens" Lisp-1 Clojure's minimal syntax is, in my opinion, a gigantic improvement o
by snprbob86 13y ago
You're dangerously close to trolling, but I'll comment anyway.
> a "I hate parens" Lisp-1
Clojure's minimal syntax is, in my opinion, a gigantic improvement over Common Lisp. And I say this as a person who quite likes parens. I feel similarly about Lisp-1s, but that is well trotted territory: Lisp-1s have won.
Parens are overloaded in traditional Lisps for both invocation and grouping. The introduction of vectors with square brackets makes a lot of code a great deal more readable at virtually zero cost: It's still homoiconic. Similarly, the inclusion of curly braces for maps is wonderful, as it makes maps a lot more common in Clojure than they would otherwise be in CL, which is a good thing for most business logic.
> replicatable in CL as a library
Defaults matter. A lot. Presence in a library is insufficient. The fact that seqs et al are in core means that 100% of Clojure libraries use those abstractions. That's a big deal.
> I don't understand why the libraries and macros to create similarly compelling interop over ABCL weren't developed instead
Rich discussed this on the CL mailing lists long before Clojure or even his first attempt, dotLisp, ever existed. See [1] and [2]. In short, interop needs to be planned for at the lowest levels to make it pleasant to use and efficient to execute. And it's not just JVM interop: Clojure was designed for $SOME_HOST interop, so ClojureScript interops as nicely with JavaScript as Clojure does with the JVM. CL would have two different libraries with two different ideas of interop for two different host platforms.
> I don't know why Clojure was created as a new language
I think you have a different definition of the word "language" than I do. Look at PG's Arc. It's built on a scheme implementation. It's not so much a new language by your definition as it is a set of scheme libraries. But that's what a language is: A common base vocabulary encoded with a well known set of syntax and semantics rules. Clojure could be implemented (quite trivially, thanks to the aforementioned careful hosting design) as a set of libraries to CL, but it would still be a new language.
[1] https://groups.google.com/d/msg/comp.lang.lisp/3-X76dTw8dI/I2oOzMg4G-MJ https://groups.google.com/d/msg/comp.lang.lisp/3-X76dTw8dI/I...
[2] https://groups.google.com/d/msg/comp.lang.lisp/3-X76dTw8dI/sJOFnp1puKMJ https://groups.google.com/d/msg/comp.lang.lisp/3-X76dTw8dI/s...
Snippet from [2]:
If one were starting from scratch,
and supplied a platform like .NET, would one define Lisp the way CL is
defined?
I would hope the answer is 'most definitely not'. For instance, .NET
provides for numbers, characters, strings, arrays, hashtables, exceptions,
namespaces, files, streams, user-defined types, a type hierarchy and
inheritance, I/O, object creation and initialization, reflection etc. Should
a language define its own incompatible versions of these things in such an
environment?
- ashr 13y agoWish I could upvote more than once.
- kenko 13y ago"Parens are overloaded in traditional Lisps for both invocation and grouping." And boy do I wish they were overloaded the same way in Clojure. I hate the fact that I have to say (cond (some-long-predicate involving multipler-parameters) (what-to-do has to go-on-the-next-line because-of wrapping) (here-is-the-next predicate) [(func1 arg1) ...]) It's very easy to end up in this situation (and it's not always just a sign that you need to refactor). It messes things up visually, and it also means that #_ doesn't work to comment out an entire test-and-expression (likewise #_ doesn't comment an entire binding-plus-binding-expression in a let), because it's not just one s-expression. I don't really understand the rationale, tbh (in fact I don't even know what it's supposed to be to try to understand it); somewhere I saw the observation that there's no need for you as a macro writer to make the client of the macro use parens for grouping when you can just call (partition 2 ...) on the arguments, which is true enough (at least, as long as the unpaired args in a larger group (e.g. binding vector) or are the tail of the arguments to the macro, captured as a rest param), but ... I kind of doubt that CL and Scheme went with the form of let, cond, etc. that they did out of convenience for implementation of the relevant macros. And even if that were the original motivation, those forms have other benefits.
- snprbob86 13y agoI'm not sure how your cond example is related to vector syntax. The decision to use (partition 2 ...) style pairs, rather than extra brackets is orthogonal. The more important point of literal syntax for composites other than lists is the fact that they are resolved at read time. This means you don't need a macro to have grouping. With (some-macro ((f x) (g y))), you need to force expansion inside the parens. Quoting (some-function '((f x) (g x))) requires forcing evaluation in your function. You could use (vector (f x) (g x)), but now that means some-function gets a vector argument and some-macro would get a list argument with first element 'vector. In Clojure, (some-function-or-macro [(f x) (g y)]) both have a vector as an argument because of the read-time behavior of data structure literals. Huge win in my book.