Clojure.rb
blog.fogus.me
blog.fogus.me
I ran into a few issues that nudged me toward Clojure:
1. Although Python has a richness of libraries, there were still some niche, domain-specific libraries available only in Java that look really appealing.
2. I looked at learning Java a few times, and I had a hard time justifying spending a lot of time learning it. The gains didn't seem that big for the tedium I was feeling doing the reading/exercises.
3. Lisp syntax is quick and easy to learn.
4. Functional programming makes more sense to me. For example my Python style involves an unreasonable amount of list comprehensions.
5. For scientific/numeric computing, baked in parallelism/concurrency is extremely appealing.
6. I was also considering learning R, but when I saw Incanter have been hoping I could learn Clojure and make use of this excellent library. That way I con't have to move between a general purpose language and a data analysis language.
I suspect I'm not alone.
Personally I spent a long time in the Java world and then migrated to Python and Ruby. I was shocked at how easy to use many libraries are in the Python world. Libraries like Feedzirra, Mechanize, Python Twitter Tools and so on don't really have equivalents with respect to ease of use in the Java world.
Except these are exactly the kinds of libraries that are easy to write in Clojure. Yes, it's important to have these excellent utility libraries, but having those is just a function of time and the size of the growing community - nothing inherent to Python itself.
But then you start looking at these really, really powerful mature Java libraries like Joda, Lucene, Neo4j, Netty, Colt, LWJGL - and you realize that creating or adopting a simple idiomatic Clojure wrapper for your use case is going to be downright exciting and fun!
That plus clojures inherent concurrency support seems like a pretty awesome mix to me.
[1] I've used lots of python and some clojure but never done heavy numeric computation in either
Yep. This is what a beginner friend told me when we compared it to Java.
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...
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 :]
(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.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)
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...
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 :]
My day job is Java mainly with some javascript mixed in, did a lot of PHP too. I used to hate JS, untill I learned about closures (and libraries like mootools and jquery). Having functions as first class citizens is truly nice!
I can see that the concept of immutability has a lot of value in a world where multicore reigns. And seeing code as data sounds like an awesome feature. But for me the question remains, how do I use it in practical everyday use? I mean, after 7 years of developing OO has ingrained to my mind. How do I transform that OO mindset into a functional one?
Yeah, perhaps I've become lazy, but most tutorials I've found don't tell me anything usefull. They show me how to print fibonaci numbers. Great, but how many times have you needed to generate fibonaci numbers? I need to know how to sort a list, find your next connecting flight or make a transaction to deposit 100 USD on a bank account.
I've build and helped design a couple of systems I'm proud of, even though I can see big flaws in all of them looking back. I've been most productive in garbage collected OO languages. I'm not willing to throw all that experience away but I am willing to accept that there are better ways to solve problems in code.
I see great potential emerging from both JVM / Closure and .Net / F#. If anyone can give me pointers to resources which learn me how not to reinvent the functional wheel, but how to be more productive in my day-to-day job, I'd be deeply gratefull.
If you want to learn functional programming, I'm of the opinion that Haskell is a great language to learn it. Then again, learning by immersion works for me, and may not for you.
In any case, Real World Haskell does a good job of explaining, well, real world examples. And "Learn You" is a nice intro to the language itself.
I've been reading learnyou over the past few days, and I can definitely feel the wheels starting to turn. I'm really looking forward to finishing it and diving into Real World Haskell.
Though I'll definitely give Clojure another try once I have a better grasp on the mindset with which to approach it.
Is it a good idea to base a language off of another, in the way that Clojure runs on the JVM and relies on Java libraries for the places where there isn't a pure-clojure alternative? I go back and forth, because I don't want to see Clojure take a hit if Java starts plunging. But when I look at it from a more practical perspective, the interop gives Clojure an essential ingredient -- without it, I doubt Clojure would thrive.
Some of the limitations of Clojure like the lack of TCO and continuation were due to the JVM. Parrot VM has these features. You also get to access libraries implemented in other languages, though I'm not sure how much libraries are in reality.
http://rubyconf2009.confreaks.com/21-nov-2009-10-25-clojure-...
Then again, maybe it's just because I'm reading Metaprogramming Ruby right now.
This is true in my experience. And this is the reason I stay away from Clojure, although I have great respect for Rich Hickey and admire many of the decisions he made in its design. The migrants seem (completely subjective perception) to be less the thoughtful ultra competent core Ruby devs,(who seem to have largely stayed on in RubyLand) and more ... vocal .... folks from the Ruby on Rails wing of the Ruby community. DHH is strident and competent. A lot of his followers/emulators picked up just the stridency.
1. Those that are going through some serious growing pains.
2. Those that recently went through the same growing pains, and have much sympathy for group 1.