Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

>> My understanding is that Clojure is meant to be Scheme like, but it is not fully compliant to a Scheme spec, my only guess is due to JVM specific nuances, but I could be wrong.

Clojure's syntax and semantics are quite different from Scheme and Common Lisp:

https://clojure.org/reference/lisps

https://www.more-magic.net/posts/thoughts-on-clojure.html

Most differences are due to design choices, not merely JVM nuances. A few differences are due to JVM limitations at the time that Clojure was designed.

I don't think any attempt was made to comply with a Scheme spec.



sort by: page size:

>Why is Scheme/CL superior to clojure ?

Clojure's license choice is unideal: the GPL-incompatible Eclipse Public License. On the JVM, it's startup performance is quite slow, and personally I don't like the Java environment at all. Furthermore, the syntax choices baffle me: Having to specifically know when a form uses () or [] is just odd. The 'let' form stands out as a good example of Clojure's bad language design choices. There's also no tail-call optimization, one has to explicitly use a 'recur' form to approximate it. I'll stop here.

Now that I've ranted about that, here's what I like about Clojure: The persistent data structures and the concept of transients. Both of these can be implemented in the Lisp of one's preference, though, and someone's already done the basic work for my Lisp of choice: Guile Scheme.

>CL, Scheme doesn't seem to have as much library support

Any decent CL or Scheme implementation gives you access to a C FFI, which provides another ocean of libs. But yes, there are fewer libraries generally, but people were okay with that for Clojure. Clojure hackers wrote a whole bunch of libraries because they were excited about the power the language gave them. If more people would recognize the immense power and value of CL and Scheme, libraries would cease to be an issue, people would write the missing bits.

I work on a GNU/Linux distribution written almost entirely in Scheme. I think that's a pretty practical application, and good evidence that Lisps that aren't Clojure are good choices, too.


> the only major difference I see between what you're calling 'clojure' and a lisp is that clojure compiles to JVM

it's always better to ask than to make incorrect assumptions


> So you admit the syntax is not as brief or as clean when you lose Clojure's data structure literals, and you have to write additional code for each type to get there?

I didn't admit anything like that. I showed you that vectors are well integrated in Common Lisp.

> Personally I wouldn't call Common Lisp a low level language.

I wouldn't either.

But then I didn't call Common Lisp a low level language. I said: 'Here (and in many other places) Common Lisp is a low-level language' - which means that Common Lisp is PARTLY a low-level language - for example no detection of modification of literal data is required/provided - the programmer has to make sure data can be modified when necessary. A higher-level data-structure would probably require detecting this or would provide only immutable data types. Common Lisp has many relatively low-level features, from cons cells to directives telling the compiler to avoid runtime type checks. Having singly-linked lists is much lower-level than persistent sequences of Clojure.

Generally it's not surprising that Common Lisp has lots of low-level features, since it has been used to write much of itself and large parts of its runtime - where Clojure is a hosted language: large parts of the runtime, the compiler and parts of the library are not written in Clojure: https://github.com/clojure/clojure/tree/master/src/jvm/cloju...


>My understanding is that the same is true of Clojure, too.

Clojure has Korma[0], Common Lisp has Crane[1] and Integral[2].

[0] https://github.com/korma/Korma

[1] https://github.com/eudoxia0/crane

[2] https://github.com/fukamachi/integral


> Later he talks about the ugliness of Lisp syntax, especially CL, but Scheme and Clojure are supposed to be better. On what basis? I may admit scheme is elegant, but calling clojure's syntax an improvement over CL is a pretty long jump.

Having syntax for 4 different data structures instead of just one would be one of my main reasons. Also, the syntax of a lisp-1 is cleaner.


> Lots of Lisps have been backwards-incompatible with previous Lisps. Scheme, Common Lisp, Emacs Lisp, and even MACLISP and LISP 1.5 were all significantly backwards-incompatible with their predecessors.

Right. That's what I'm saying. Clojure does not care to be backwards compatible with Lisp.

> Your taxonomy of immutability and persistence is interesting

That's not mine.

Clojure took its base data structures from Haskell and modern ML.

Not Lisp.

See:

http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf

http://en.wikipedia.org/wiki/Persistent_data_structure

The book comes with examples in ML and Haskell.

http://www.amazon.com/Purely-Functional-Structures-Chris-Oka...


> it turns out that lisps are pretty good at calling into java code

I think that gives the design of Clojure too little credit. I can imagine MUCH worse ways to do it than Clojure's well-designed Java interop.


> The result of that design is that Clojure shares literally zero lines of code with other Lisps: Autolisp, ISLisp, Emacs Lisp, Standard Lisp, Common Lisp. Many basic concepts are absent, renamed or redesigned ('Atom', 'Linked List', ...). Clojure is fully incompatible to any other language with Lisp in its name.

> Programs have to be re-architectured, because the concepts are different:

"Re-architectured" can be read in a multitude of ways. Changing a few datatypes because Clojure prefers vectors instead of lists, etc., feels like it falls well below the bar for "re-architectured".

> no TCO, but 'functional'

This would hold weight if CL mandated TCO, but it doesn't.

With this in mind, I'd like to examine a few of your points from a different angle:

Racket:

- Basic concepts are the same, (atom, linked lists, '...')

- Restructuring not really needed (up for debate, depends entirely on your prefered initial design choices in either language. Racket isn't that opinionated.)

- Tail call optimization required as per Scheme standard, so is present. Note that this is not actually something Lisp mandates.

- Doesn't 'care' about side effects, community is pragmatic and will generally advise you to do whatever is practical

- Has an object oriented sub-language with message passing and so on

There are a lot of points here that, according to you, makes Racket essentially a Lisp, even your non-point about TCO. I'm curious to know what you feel about people saying Scheme is a Lisp, considering the above.

The whole debate of "Is X (a) Lisp?" reminds me of nationality debates that essentially boil down to some people saying blood is more important than culture. You seem to be taking both sides, however; arguing culture and blood (source code). You cherry pick the cultural differences like most people standing on one side of the nationality debate would and argue that just those specific differences are the most important.

That's the thing, though; Swedish people could argue however much they want that they're very different from Norwegian people. To the rest of the world, though, they're essentially the same. Especially when you start comparing them to people from Peru, Venezuela, South Africa, and so on. When you're in the bubble the very small differences are much bigger to you, but if you zoom out to get some perspective these differences are much smaller than the commonalities.


> The design of deps.edn/clojure CLI and the lack of user friendly tooling is forever frustrating.

"user friendly tooling" and ANY Scheme in the same sentence?!

I kid, but I always have held that Schemes feel like "tools for building a programming language" and Clojure feels like "an actual programming language" with its benevolent use of brackets.

Racket seems to want to inhabit the space between those two with its package system and ability to compile to an executable.

    (defn my-func [arg0 arg1] ..)    -- Clojure
    (define (my-func arg0 arg1) ..)  -- Scheme (of which Racket is one)
One thing I've always liked about Racket is its refusal to accept (if )s without else statements, insisting instead on using (when )s.

> I like Common Lisp, but it's much easier to build useful apps in Clojure.

Unlikely.


> but I got the impression it has learned next to nothing from Clojure

I think that's a feature, since Clojure basically has no Lisp compatibility at all. No prior Lisp code runs in Clojure as it has zero backwards compatibility. Clojure has randomly renamed concepts which were known in Lisp already or removed them. Lists are no longer lists, ATOM means something entirely different, etc etc.

Though the compatibility of LFE with other dialects isn't that great in general:

http://lfex.github.io/hyperpolyglot/


> Clojure is a Lisp. One of the distinctive things about Lisp is that it has dialects.

When one of those dialects is completely source-incompatible with every other dialect (the rest of them share non-trivial programs freely), and doesn't share the same core features as every other dialect (like list structure), then why is it still a dialect and not a different language? Calling all the other Lisps that share core features and run the same code different versions of one language makes sense to me; I don't see the point in applying it to any language that borrowed a couple ideas.

If I have a large codebase written in (any) Lisp, will porting it to Clojure be significantly easier than porting it to Javascript or Ruby or any other modernish language? Not really; it's a complete rewrite either way. That sounds to me like it might just be a different programming language.


> like reading a Lisp book and then trying the example code in those languages - and then it does not work...

Does SICP work in Common Lisp these days? Or is Scheme also not sufficiently a lisp?

> CL is a specific branch of the Lisp tree. Clojure is a new tree, based on roots in Java (runtime and interop), Lisp (various ideas, like expressions, macros, ...), FPLs (ideas like 'persistent' data structures, ...

I would definitely agree with this.

EDIT: It occurs to me that maybe the difference of opinion is around the whole acceptance of the notion of lisp as a family vs. Capital Lisp as a species.

It seems like the idea of strict compatibility with Common Lisp is more akin to the definition of a species (i.e. more or less able to interbreed). On the other hand, if one accepts the premise that lisp can be a family, then incompatible evolutionary changes should be expected.

Whether one considers Clojure a lisp probably depends on whether they think it bears sufficient resemblance to other accepted lisps as to constitute a family. Lions and house cats are pretty different and aren't biologically compatible from a reproductive standpoint, but share a lot in common such as a similar morphology and common ancestor. Common ancestor is a sticky point, because presumably some Common Lisp implementations don't literally share code with prior lisps... A clean room Common Lisp couldn't meet that standard, for example.

Fun discussion for sure.


>Anyways, I kept reading places that lisp macros and c macros were completely distinct, which seems untrue after a couple years of trying clojure.

I haven't used Clojure macros but as a programmer that uses both C and Common Lisp, I can say with good authority that C macros and CL macros are very different.


> sometimes I feel that it is not a true lisp.

That feeling may be the result of some questionable syntactic design decisions in Clojure.

Hickey went over Lisp syntax and tried to remove parentheses wherever possible. (It was the hip thing, PG's Arc did it, too, which may be where Hickey got it from.) As a result, you get a sub-par editing experience —generic sexp-based structure editing doesn't get you as far as with a Lisp— and diminished readability once you get above three omitted pairs of parentheses in a row.

On the other hand, Clojure arbitrarily mandates a secondary kind of list literal in some places of the syntax, again making Clojure harder to write and edit. I don't even see a readability benefit, but of course YMMV.

TL;DR: Clojure syntax is a "complected" derivative of Lisp :-)


> I’ve seen people saying that but never with an argument as to why. What do they mean?

I don't know but if I had to guess, it's because lisp is list processing language, and Clojure doesn't really support lists (I mean, it's possible to make some, but there are none out of the box); instead it has a variety of trees that mimic the runtime performance of lists, arrays, hashes, etc.


> It's a LISP designed for the JVM

Honestly, this should be the Clojure tagline. Would solve a lot of the confusion. To be truthful, I never pictured it that way, but to be fair I think Clojure sells itself as more than that.


> [I] have never seen it in practice. Understandable Lisp isn't that compact.

Also, you are literally replying to a comment chain provoked by a post that argues, with code, exactly this point. The Clojure (a Lisp dialect) version has the same core logic as the Java version. The core logic is virtually inarguably just as readable as the Java version. And it is just shy of an order of magnitude fewer lines of code than the Java version.

So here's an example from a real, live code base of understandable Lisp, in practice, that is 10x more compact than the Java version.


> Like lots of languages. Incl. Lisp itself.

Sure, I'm just highlighting that your statement about Clojure is correct when it comes to compatibility against other languages while being incorrect if you consider it within the Clojure ecosystem itself.

next

Legal | privacy