22 ms·
Clojure or: How I Learned to Stop Worrying and Love the Parentheses
- confuzatron 16y ago"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 16y agoThe 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 16y agoFlippant 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.
- mquander 16y agoHere's the "LINQ" of Common Lisp, which may look "different" enough to convince you: http://www.unixuser.org/~euske/doc/cl/loop.html http://www.unixuser.org/~euske/doc/cl/loop.html (It could be implemented identically in Clojure, if you cared to.)
- confuzatron 16y agoThanks. To my untrained eye that looks more like it could be called a DSL than the article, where mostly it's just creative whitespace formatting, as far as I can tell. What's going on with the underlining?
- mquander 16y agoRe: the underlining -- no idea, just an instructional aid, I guess. Here's another example that might look "DSLy": http://www.brool.com/index.php/pattern-matching-in-clojure http://www.brool.com/index.php/pattern-matching-in-clojure The pattern matching macro "match" is written entirely in Clojure, without any compiler tricks. I wish I could do the same in C#! (I'd need to have a bunch of cruft defining a predicate object with options for each match criterion.) All of these techniques boil down to how easy it is to do two things in a language: - To write DSL code in your structure of choice without having to cover it in a huge amount of syntax goop, e.g. the loop macro or the magic LINQ syntax. - To analyze and transform that DSL code programmatically, in a way that's more structured than simple string manipulation, so that you can do the right thing with it. C# 2.0 was very bad at both of these. C# 3.0 improved a lot, by adding lambda expressions for the first, and allowing you to analyze C# expressions as a syntax tree. But Clojure (& Lisp in general) is really good at both.
- grayrest 16y agoThe 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 16y agoYou 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.
- nathanmarz 16y agoThe snippets are Clojure code that use the Cascalog library. Cascalog has the look and feel of an embedded language.
- c00p3r 16y agoAny parentheses other than () are evil. ^_^
- mahmud 16y agoAnd rightly so, because they wouldn't be parentheses, rather braces, brackets, angle-brackets, and guillemets.
- deleted 16y ago[deleted]
- c00p3r 16y agoOK. 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-sussman-lectures/ http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussma... - Lecture 1b: Procedures and Processes; Substitution Mode.
- mahmud 16y agohttp://en.wikipedia.org/wiki/M-expression 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%29 http://en.wikipedia.org/wiki/Dylan_%28programming_language%2...
- c00p3r 16y agohttp://mumble.net/~campbell/scheme/style.txt 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.
- overgard 16y agoI 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 16y agoI 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 16y agoYour 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.
- pavelludiq 16y agoI can relate to the feeling of angst one gets when he encounters an unfamiliar dsl in lisp code(or any language that uses them a lot), but its the same kind of angst i feel when i encounter anything unfamiliar, its perfectly normal. But such irrational fears are, well, irrational. I need better reasoning against lisp(or any other powerful non mainstream language) than "it looks scary", or "it isn't intuitive".
- DougBTX 16y agoI think he started out well, pointing out that SQL is a DSL for database queries. But the mapping between Cascalog and SQL wasn't clear, without further explanation it seems to be different for the sake of being different. I would have appreciated a DSL which could obviously be used as a way to query an SQL database more than the examples in the article.
- jallmann 16y agoNit: 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 16y agoThe 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 16y agoActually, 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.
- nathanmarz 16y agoHere's infix math from the Incanter library for Clojure: http://data-sorcery.org/2010/05/14/infix-math/ http://data-sorcery.org/2010/05/14/infix-math/
- mquander 16y agoYou can change prefix expressions to infix with a macro, if you like; didn't you read SICP? Your DSL can look however you want it to, as long as there are some parentheses around the ends of it.
- jbz 16y agoI 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.
- nathanmarz 16y agoI'm not bashing C#. I'm just saying that you couldn't define Linq in vanilla C#. It had to be implemented as part of the compiler. In Clojure, you can create embedded languages without modifying the compiler. That's all I'm saying.
- jbz 16y agoI can appreciate and understand that you didnt mean to come of as combative, but to me it did come off that way - and others since im not the only one pointing this out. Can you name the compiler change that enabled Linq without looking it up? Can you define Linq, what it basically is? It feels like if you could you wouldnt make such a statement since all Linq is at its core is an iteration engine. Its literally just methods you dump your collection into plus an anonymous method on top and vrooom goes the engine applying the method to each item. The pretty syntax form you usually see is not actually Linq the framework and leads to significantly more problems than it solves, its basically just for PR purposes. Edit: This feels like it might get out of hand and spin into a good old nitpicking programmers war. Reading my post again it came out way more confrontational than I meant, and I didnt mean any insult by it. My main contention is that the Linq syntax is often confused for the Linq framework - they are not in the same state let alone ballpark. Plus the argument can be made (and i would agree to a large extent) that it wasnt the compiler that was modified to allow Linq, it was Linq that was waiting in the wings for the compiler team to implement features they had planned quite some time before. However I am also being a stickler and stubborn, I nitpicked when even from my point of view it wasnt such a large error - it was the way it disrupted the flow of a pretty good article I was getting into, thats what made it stick out for me.
- mark_l_watson 16y agoGreat 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).
- ataggart 16y agoclj-stacktrace improves things quite a bit. http://github.com/mmcgrana/clj-stacktrace http://github.com/mmcgrana/clj-stacktrace
- mark_l_watson 16y agoI do use it on one project and am semi-satisfied with it.
- gfodor 16y agoNot sure if you realized it, but saying someone used a strawman is generally an insult to their argumentative abilities :)
- mseebach 16y ago"SELECT Person FROM Age ..." .. Let's just that it's not SQLs fault if you run into problems here.
- mark_l_watson 16y ago:-) right you are - I had not thought of that.
- cageface 16y agoLispers 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.
- aerique 16y agoFor the particular task of list processing its syntax is pretty optimal ;-)
- nathanmarz 16y agoI'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 16y ago
- pvg 16y agoThere 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 http://www.paulgraham.com/onlisp.html
- nathanmarz 16y agoExcellent 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 16y agoThere 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 16y agoI'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 http://strangeloop2010.com/talks/14487
- knodi 16y agoI 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 16y agoI'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 16y agoErlang, 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-manager-more-scalable/ http://www.serpentine.com/blog/2009/12/17/making-ghcs-io-man... http://www.slideshare.net/jboner/akka-scala-days-2010 http://www.slideshare.net/jboner/akka-scala-days-2010
- grogers 16y agoI 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.