4 ms·
No intention to bash Clojure - it's a wonderful platform & community. But... I recently switched back to Ruby from Clojure. It was rather pragmatic - i'd love
by kunley 16y ago
No intention to bash Clojure - it's a wonderful platform & community. But...
I recently switched back to Ruby from Clojure. It was rather pragmatic - i'd love to experiment more, but I needed to use some libraries I knew very well; also the peak of productivity which Ruby offers to me was tempting again.
And it happened after a couple of months I had to look to chunks of my Clojure code to port it to Ruby as it had to be incorporated in a new product. And...
It wasn't so easy to decipher it at a first glance. I also had to jump back into a state of mind in which I created a bunch of macros to realize wtf were they doing.
I always was a big fan of macros but this time I realized they like write-only memory. Hard to share with others without careful documentation. Even hard to share with future self :)
I just don't have this issue when reading Ruby. In fact, most of Ruby code, mine or some else's, is instantly comprehensible. There's something in the brain or what...
- fogus 16y agoI doubt anyone reads into what you've written as bashing. There is a definite complexity cost to using macros, but as you will hear often... avoid using them unless you absolutely need to... and even then try using a function. A similar sentiment can be said for monkey patching, metaclasses, and eigenclasses. They are advanced techniques that introduce complexity and should be avoided if at all possible. It's the cost of power I suppose.
- kunley 16y agoActually I never took the argument 'avoid macros unless absolutely needed' seriously. Macros are sexy and fun to code. The ease of writing macros in a syntax-less Lisp is ubercool. And programming should be fun, right? I code in Ruby using monkeypatches and dirty hacks. I mostly use functional style with lots of blocks and lambdas and rarely write a proper class. So I'm a programming language power abuser, and proud of it ;) But here I'm talking about a cognitive experience of reading code written some time ago or by someone else. Let's say that with macros/metaclasses/DSLs you prepare some environment to make your final code more spicey, and then you write that final code. My conclusion is that for Clojure my reaction on reading such code was usually "WTF?!?", and for Ruby: "Ahhh that's clear". Btw I wonder why someone downvoted my original comment.. [edit] One more thing on macros: the On Lisp book which is armed to the teeth with macros was the cause why I learned Lisps years ago :]
- fogus 16y agoCertainly on my own projects any and all dirty hacks are fair game. When I work with others I try to avoid being cute for cute's sake. I suppose it's no great revelation that some prefer Ruby syntax to Clojure's. However, I can say that Clojure works hard to reduce the number of parens that you might find in similar Lisp or Scheme code. For example, the `let` form in Common Lisp looks like: (let ((a 10) (b 20)) (* a b)) After many years using CL in school I can sympathize with the idea that Lisp is full of parens. Common Lisp's `let` is nicely delineated and is easy to reason about... for macro writers. Experienced Lisp users don't blink an eye at this. However, Clojure takes a different approach: (let [a 10, b 20] (* a b)) There are still parens, but they've been reduced leading to (IMO mind you) a cleaner look. Our opinions clearly differ on aesthetics, but I think it's worth noting that Clojure libraries will strive for the latter over the former.
- kunley 16y agoIt's true that average Clojure code looks cleaner than average CL code. Still I'm looking for something more cleaner, still being a Lisp. Time for Arc maybe :]
- fogus 16y agoI wish I could speak for Arc, but sadly I can't say that I know more than superficialities. Hopefully someone else can chime in. Let me say that the example with `let` is just a small example of an over-arching trend in the way Clojure code looks vs. CL. I would love to hear more about Arc's approach.
- DanielRibeiro 16y agoRegarding macros: I wrote about this in On Lisp. A complex macro may have to save many times its own length to be justified - PG, Succinctness is Power (http://www.paulgraham.com/power.html http://www.paulgraham.com/power.html) Having that said, macros, and ast manipulation overall, are the most powerful form of metaprogramming. Ruby supports this with ParseTree and Ruby2Ruby, however ruby supports easier and less powerful forms of metaprogramming. I find this useful, as you can use the least complex form needed for a job (and refactor up/down as time goes by). On the other hand, I find Clojure much more valuable for its applied research in STM and high level concurrency. But I digress...
- kunley 16y agoYeah I always liked PG's argument, he's using macros in a very powerful way building bottom-up lots of valuable code. Still succinctness doesn't seem to apply to CL usual practices and Clojure seems to have this legacy inherited (actually, not in the core, rather in the community libs). I'm talking about full-sentence-like-function-names-without-any-abbreviations. There was a explanation by the CL community that long names don't hurt as most editors (read: emacs) support smart tab-expansion of existing symbols, so typing it isn't a PITA. But still long names do hurt reading the code! My brain seems to visually reject code with such names. Add Clojure's type annotations esp. in java-interop code and there's quite a mess on screen.. so i have to read the code carefully sexp by sexp instead of grasping it with a quick glance like in Ruby.. Maybe it's time to try Arc it seems much more succint :]