

Clojure or: How I Learned to Stop Worrying and Love the Parentheses - mrduncan
http://nathanmarz.com/blog/clojure-or-how-i-learned-to-stop-worrying-and-love-the-paren.html

======
cageface
Lispers rightly tout the malleability of the syntax as a killer feature. The
big problem is that any language you build in lisp is still pretty much lisp.
If you're not already sold on s-expr syntax, and a lot of programmers, rightly
or wrongly, don't like it, the fact that you can replace one s-expr syntax
with another just isn't that convincing.

The irony here is that lisp's syntax will probably keep it from ever falling
into obsolescence because it can adapt to any new _general_ task but it will
also prevent it from ever really breaking into the mainstream because for any
_particular_ task it's a non-optimal syntax and a steady procession of more
specialized alternatives suit most people's needs better.

~~~
nathanmarz
I'll admit that learning to be effective with Lisp's syntax took me a few
months. It's a matter of getting used to that way of thinking about
programming.

Now that I'm fluent, I strongly prefer the s-expression style for most
problems. The uniformity of Clojure means that I can use the sequence library
for an unbelievable variety of tasks. And I love that operations like "+" are
just like any other function and can be passed around.

Another important point is that when you make a DSL in Lisp, that DSL can
interoperate with _all your other DSL's_.

~~~
cageface
I programmed pretty heavily in Common Lisp from about 2000-2003 and I got over
the parentheses too after a few months. I can't say I ever really came to
_love_ the syntax though. I always thought of it as the price I had to pay for
macros. I did get pretty tired of the religious zeal of a lot of lispers
though. Too many insist that lisp is the "right" way to design a language and
refuse to see it as the collection of design compromises it is, like every
other language.

------
overgard
I think the spirit of the post is right on, but I'm not a fan of the example
given. That's the kind of code that scares people away from lisp. Which isn't
to say it's bad code, but it's not nearly intuitive enough to use as an
example.

~~~
nathanmarz
I wanted to show an example of an embedded language people could relate to.
Querying is something most everyone has done and has felt the pain of doing
from other language. Any other non-trivial example of an embedded language
would be even harder to understand b/c the problem domain wouldn't be familiar
to the reader. It's a tough concept to communicate, I did my best.

~~~
sigzero
Your best...was good enough. I don't follow Clojure much but I understood what
you were trying to get at through the article. Nice job.

------
mark_l_watson
Great article. Probably no coincidence that Nathan uses SQL as a straw-man
since he is interested in data oriented languages and wrote the nifty Cascalog
DSL (which, BTW, I am evaluating for use at work).

I share his interest in Clojure, but some little things like poor stack traces
still keep the experience of using Clojure from being totally fun. I use
Clojure for work, but I am still mostly using Ruby for my own projects (with
some Clojure).

~~~
gfodor
Not sure if you realized it, but saying someone used a strawman is generally
an insult to their argumentative abilities :)

~~~
mseebach
"SELECT Person FROM Age ..." .. Let's just that it's not SQLs fault if you run
into problems here.

------
grogers
I think most of what is good/unique about clojure doesn't come from being lisp
though. For example - its concurrency constructs, seq/lazy-seq abstraction,
persistent data structures that work with seq, java interop, etc.

Being a lisp doesn't hurt it, especially in the context of DSLs mentioned, but
I don't think it defines it either.

------
jallmann
Nit: the technical term for "integrated language" mentioned here is domain-
specific language. People spin off DSLs from Ruby all the time.

Incidentally, one could argue that SQL is the most widespread DSL there is.

Edit: The author mentions this is basically a DSL in his post, which I missed
the first time around. Not sure why he didn't just stay with that nomenclature
though.

~~~
prospero
The distinction being drawn here is between a DSL which is defined in terms of
pre-existing syntax, and one which defines its own syntax.

The "integrated languages" that are discussed do not need to be stored in
strings, or have some sort of special pre-processing step to coexist with the
primary language. In Clojure, a Cascalog query is a first-class structure
simply by virtue of being defined in terms of Clojure syntax. Integrating LINQ
into C#, on the other hand, required modifying both the compiler and IDE. And
as pointed out in the OP, SQL is a second-class citizen pretty much everywhere
you look, which leads to issues like injection.

~~~
kgo
Actually, Lisps conveniently sidestep the whole issue by refusing to have ANY
syntax. Which is fine if you like it. But you could just as easily argue lisp
is bad for DSLs because you can't, for example, define an infix operator.

~~~
scott_s
I think "Lisp has no syntax" is an unfortunate meme. Lisp has a syntax. It's a
very simple syntax for defining trees, and you're basically using it to write
the abstract syntax tree for your program, but it still has a syntax.

~~~
kgo
Yes of course, but in the context of a DSL, you're not really defining a new
syntax. You've still got an AST at the end of the day.

And of course, this isn't an attack on lisp. If it works for you, cool. But I
just don't see how that distinguishes itself from a ruby DSL like say rspec.

I think the nicest feature of lisp DSLs is that lisp doesn't have the concept
of an operator, and most langaguages make if difficult to define a function
called __or <\- or something like that. But you can do that in Haskell or or
ML, it's not really exclusive to S-exps.

~~~
scott_s
I'm unfamiliar with rspec, but the major difference between designing and
implementing DSLs in Lisps versus other languages is _ease of code
generation_. That is, actually generating new code based on what the user of
the DSL supplies. In Lisp, this is done because it's trivial to receive the
AST that defines what the user wants to do. Then you can generate code
directly based on that AST. No need for reflection or any such trickery
because it's all just lists of list.

In most other languages, if that sort of transformation is even possible, it
is much less direct.

------
pvg
_There have been many attempts to articulate the benefits of Lisp-based
languages before, but most of these attempts seem to end in futility._

Really? I think someone even wrote a whole book that's mostly about macros,
embedded languages and so on.

<http://www.paulgraham.com/onlisp.html>

~~~
nathanmarz
Excellent book, but no one is going to read an entire book on Lisp unless
they're already interested in the language.

What I mean by "articulate the benefits" is a short explanation for the unique
benefits of Lisp that a non-Lisper can digest. That's what I tried to do in
this article by trying to show a tangible example of an embedded DSL.

PG's post "Beating the Averages" is a better example, but its argument is more
based on authority than clearly communicating the tangible reason _why_ macros
are so useful. That said, PG's posts are what got me interested in Lisp in the
first place, but I didn't fully understand the benefits of Lisp until I
started using it heavily.

~~~
pvg
There are many many many blog posts, short essays, long essays, old usenet
posts, mailing list rants, you name it that are about 'the benefits of Lisp'.
Now, you may not have found one that was very clear to you and that's fair
enough. But to say they 'end in futility' is really pretty presumptuous.

------
puredanger
I'm very much looking forward to seeing Nathan talk about Clojure and Cascalog
at the Strange Loop conference in October!
<http://strangeloop2010.com/talks/14487>

------
knodi
I don't know why there is so much Clojure junk on HN but if your thinking
about picking up Clojure you'll be better of learning Erlang instead.

~~~
phren0logy
I'm all for a contrary point of view, but it would be nice to see you give
some reasoning. I have heard some good things about Erlang, but the syntax
isn't exactly luring me in. Why would I look at Erlang when I could get good
concurrency and bajillions of Java libraries with Clojure?

~~~
gtani
Erlang, scala/akka, haskell/ghc and clojure all have compelling takes on
concurrency (C#/F# too). In erlang's case, it's the lightest of lightweight
processes. I've seen blogs describing erlang apps spinning up millions of
processes. Those are the kinds of numbers that akka and ghc are shooting for
(I don't have an akka reference:

[http://www.serpentine.com/blog/2009/12/17/making-ghcs-io-
man...](http://www.serpentine.com/blog/2009/12/17/making-ghcs-io-manager-more-
scalable/)

<http://www.slideshare.net/jboner/akka-scala-days-2010>

------
c00p3r
Any parentheses other than () are evil. ^_^

~~~
mahmud
And rightly so, because they wouldn't be parentheses, rather braces, brackets,
angle-brackets, and guillemets.

~~~
c00p3r
OK. Let's state in differently. Clojure is a functional language with a Lisp-
look-like syntax, inspired by Lisp. But it isn't a Lisp.

The one of the fundamental part of the Lisp philosophy is to keep a syntactic
sugar away, while Clojure is a collection of various syntactic sugar on top of
something which looks like Lisp's syntax.

The statement that "Clojure is a dynamic programming language that targets the
Java Virtual Machine" is true, while "Clojure is a dialect of Lisp" is just a
very-very clever marketing statement.

 _^ &~@%#{}[]_ \- what all this shit is supposed to be? One must learn it.
With all that crap Clojure is just another language, which locks like Lisp,
especially for those who never saw emacs-lisp or Arc before.

[http://groups.csail.mit.edu/mac/classes/6.001/abelson-
sussma...](http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-
lectures/) \- Lecture 1b: Procedures and Processes; Substitution Mode.

~~~
mahmud
<http://en.wikipedia.org/wiki/M-expression>

By far, the cleanest Lisp dialect out there is Dylan, and it uses Algol
notation, not s-expressions:

[http://en.wikipedia.org/wiki/Dylan_%28programming_language%2...](http://en.wikipedia.org/wiki/Dylan_%28programming_language%29)

~~~
c00p3r
<http://mumble.net/~campbell/scheme/style.txt>

_The reader of the code should not be forced to stumble over a semantic
identity because it is expressed by a syntactic distinction. The reader's
focus should not be directed toward the lexical tokens; it should be directed
toward the structure, but using square brackets draws the reader's attention
unnecessarily to the lexical tokens._

But it is not only about a style. When [x y] means a different thing than (x
y) it is a different language construction, with different behavior.

------
confuzatron
"There's one huge difference between Cascalog and Linq: Linq is part of C#.
You can't define Linq in terms of regular C#"

So, the code snippets in this article aren't written in Clojure, but instead
in some other custom language? I dont know Clojure, but those examples look
very much like that crazy foreign Lisp 'nested parenthesis talk' to me.

~~~
mrduncan
The code snippets are Clojure, but that's the point. Nothing was added to the
Clojure language itself in order for this to be possible. Linq would not have
been possible (in it's current form anyway) without adding new features to the
C# language itself.

~~~
confuzatron
Flippant response: you're saying that nothing was added to Closure in order
for some Closure code to get written? This is not unprecedented.

Seriously - I don't see what's unusual about the syntax of these examples that
makes them a DSL that doesn't just look like clojure code.

If my Linq implementation is allowed to resemble the language for which it is
implemented, then I can easily write a 'Linq' implementation in plain C# that
will look just like plain C#. (Although I grant that LINQ refers to the syntax
additions to C# and not just the library)

Not hugely worked up about this, just feeling a little 'Emperors New Clothes'
about it.

~~~
grayrest
The point wasn't to make it not look like Clojure, the point was to express
querying constructs in a way that's natural to the language. This isn't
impossible in any language and is actually fairly common within the domain
(e.g. SQLAlchemy for Python works similarly though operator overloading).

The point he's trying to make is that the default way of doing things in a
lisp is to adjust the language constructs to fit the domain of the problem.
This (generally) results in a simpler mental model of the problem domain and
less code. It's not a about being ABLE to do it. You can do something similar
in most languages, but there it's just not as easy, not the default, and not
as flexible.

~~~
confuzatron
You might be right, but if so it sounds like the talk of Linq, and syntax, and
'DSL's served to obscure his actual point, which is a shame.

Guys, honestly, downvote if it makes you feel better.

------
jbz
I feel like I'm nitpicking but I couldn't let it go, and yes its already been
mentioned once but I feel that argument offered by confuzatron was lacking.
I'm referencing to your characterization of Linq in C# as something
inextricably linked to the language, how you cant even begin to separate it
from the language.

Straight off the bat the most glaring problem with that statement is that Linq
is not part of C# in any way shape or form since all C# code is compiled to
bytecode, it would be literally impossible for C# to have Linq and for it to
not be available for the rest of the languages supported by dotNet. The funny
part is the expressive form of Linq that reads like a sentence is not even
fully supported by C#! Only VB.Net has fully implemented Linq expressiveness.

There are many more reasons that argument is wrong, but I feel just pointing
out that one above shows how far off it is.

In my experience its almost always best to shy away from hyping your idea of
better by knocking the competition, your article stands well on its own and C#
has so many obvious flaws that theres no need to add to it. Stick to whats
good about X, not whats crappy about alternative Y.

Again all in all an interesting read since im not familiar with Clojure, but I
just had to nitpick.

~~~
prospero
_Straight off the bat the most glaring problem with that statement is that
Linq is not part of C# in any way shape or form since all C# code is compiled
to bytecode, it would be literally impossible for C# to have Linq and for it
to not be available for the rest of the languages supported by dotNet._

There's no such thing as "LINQ bytecode". LINQ is just syntactic sugar that
can coexist with vanilla C# (or VB.NET, or whatever) because Microsoft decided
to modify its compiler and IDE to allow it. It is fundamentally impossible for
you or me to make a similar change, unless we're willing to eschew the
Microsoft toolchain.

In Clojure, you do not have the same limitation. That's the only point the
article was making, and it's completely correct in that respect.

~~~
jbz
see my reply to nathanmarz

