Î really love clojure, but this article is not a good plaidoyer, for a lots of reasons, the first and most pregnant being the ability of the author to vastly traverse subject he is probably not an expert about.
> Functional programming, of the kind shown in SICP, is a way to write code that does not manage the state of variables, and could therefore be partitioned to run in parallel on as many processors as you like
This is kind of true, but totally misleading, because very few tasks are actually easily paralelizable this way. When you stumble on one, you know it, and replacing map with pmap certainly is a joyful exercise, but this kind of parallelization are easy to do in any languages. The hard parts are those when you need to access shared state across threads. The facilities that clojure provide in this respect, while innovative and enlightening , have benefits that largely remain to be proven.
> languages like F# and Scala which have a complexity and "quirkiness" reminiscent of C++
Erm, sorry, what, F# reminiscent of C++, did you even try to read some code written in F# ? F# has one of the tersest syntax you're likely to find in any language. As an ML descendant it does already have a very clean syntax, and the addition of significant whitespace only adds to that.
> You can write Clojure code that derives from Java classes and overrides Java methods. In short, if you can do it in Java, you can do it in Clojure.
Yeah sure, but in practice, most people that says that didn't ever had to really handle a non trivial project with java interaction in it. I did. And frankly it can get ugly. It's good to have it, but ideally, all should be encapsulated in idiomatic clojure wrappers. While this is not that hard because java interaction is very well thought, it's a long and boring process, and when you're in the middle of a project and just needs some bit of functionnality that isn't in a clojure lib (and trust me there are still a lot of those), you tend to just use the java interop in place. And then you get back and read your code, and you cry.
In short, this is just a rehashing of what you usually hear about clojure, but with no insight of real use. My (uninformed) guess, is that the author probably didn't use clojure a lot, and frankly, this kind of stereotyped talk gets old.
Your response is more misleading than the article:
> but this kind of parallelization are easy to do in any languages.
Not if you have a GIL. Even then the languages without that limitation do not make what pmap does ... easy.
> [STM] have benefits that largely remain to be proven.
I always find this statement to be misleading. STM has been shown to greatly benefit the correctness of concurrent programs, you're managing that less by hand. The only thing that seems to be unproven is whether the performance tradeoff is worth it. It'd be nice to see some numbers that show what you lose in X% of the performance vs removing X% the amount of locking code.
> [Java interop] And frankly it can get ugly. It's good to have it, but ...
Yet far less tedious and simpler than writing a C module, or a C library binding. If you're comparing against that, Clojure's Java interop story is damn heavenly.
> In short, this is just a rehashing of what you usually hear about clojure, but with no insight of real use ...
Perhaps for you and I. But there are a lot of people in this big wide world. Uncle Bob taps into a community that's quite different from the language enthusiast crowd of HN.
Your viewpoint more myopic than the OP. Yet you get upvotes. Oh well.
You emphasize two points that I would also like to add to.
1) Functional languages makes parallel programming magically easy.
This is something that is misleading as you point out. Functional languages (where you have not used mutable state) do make it easy to convert you algorithm to run on multiple cores but that doesn't translate to an algorithm that scales well with number of cores. The problem of parallelization is not one of syntax or even semantics, it is an algorithmic one. You need to have in mind the problem and how to make it scale. Just cause you didn't use state doesn't mean that the algorithm that you wrote automatically takes full advantage of parallelism to solve a problem.
What functional programming does is allow you to more easily express the parallel algorithm when you have it as well as giving you more options in how to do so. But for now and maybe this is cultural inertia, coming up with parallel algorithms is hard regardless of language. This is a distinction that is often glossed over probably because those who are aware of it find it so basic as to not worth mentioning.
2) F# and Scala are quirky and complex
I will give a disclaimer and say that I use F# to write machine learning stuff so I am likely extra sensitive to this kind of bashing but..
That statement makes no sense and has no real meaning. Does he mean that the semantics allow undefined behaviours ala C++ or that the syntax is overly verbose or the syntax is just plain confusing? F# syntax is not so far from ML or Haskell or even python. As for undefined behaviour, strongly I doubt that applies. Scala has a formal specification. While F# doesn't have a formal specification it does have a very thorough (good enough) informal one. I am certain that it will not have implementation dependent behaviour and its strong static type system and garbage collected nature precludes the chance for un-trapped errors so the C++ style undefined behaviour can't be the issue.
F# is certainly not verbose and although Scala, being more OOP centric is a bit more wordy, both languages are quite expressive. Terse syntax is meaningless. What matters is how easy and quickly it is to correctly express an algorithm balanced with how easy it is to mentally uncompress it later (on this case F# may even sometimes be too terse! I have taken to commenting and using quite long names for complex algorithms since otherwise it takes a goodly number of minutes to decompress - especially when the code is littered with single letter variable names that the mathematics like syntaxes subconsciously promote). I will admit that where F# is clunky is the number of ways you can cast and it is a fairly big language with Active Patterns, Workflows and Async and Agents on top of the typical functional idioms. But each such feature transfers a lot of expressive power - a fair trade.
To brush aside languages like Scala , F# without having spent much time on them and in such an ambiguous manner is simply not fair. It is okay that he chose Clojure (wonderful language) but did not have the time (measured in months - fair enuff) to properly investigate all the choices but to brush them aside so trivially is intellectually dishonest, to be brutally truthful.
You know, I really want to like Clojure, but so far I'm finding it a bit of a slog, for the following reasons:
1. stack traces are very hard to decipher
2. ubiquitous laziness can lead to some really subtle bugs
3. the syntax can be extremely obtuse, moreso than other lisps
4. the basic ADT is just a keyed map, which provides a lot of flexibility but also can make data modeling very opaque, even compared to other dynamic languages
5. immutable and recursive as a default takes a lot of getting used to. things I could dash out in minutes in ruby take me hours sometimes
6. other languages have caught up enough that Lisp macros are not as game changing as they might have been ten years ago
I embarked on a project recently to explore machine learning algorithms, implementing them in both Scala and Clojure at the same time. I expected this to be an easy win for Clojure but, to my surprise, I'm much more productive in Scala, my code has fewer bugs, and I can refactor it much more aggressively. I realize that this isn't an either/or thing and it may be entirely my shortcomings at play here, but my instinct is that although Clojure is a superb lisp, it's still a lisp, and it's going to be a niche that most programmers won't choose to occupy.
"2. ubiquitous laziness can lead to some really subtle bugs"
I find myself implementing Iterable wrappers more often in Java now, largely due to the influence of Clojure lazy seqs. Then I can use the abbreviated for loop syntax, for example, without creating a ridiculously large ArrayList in memory.
I know that the Iterator pattern has been around for a long time, but I never realized how broadly it could be applied to use high level iteration constructs while keeping a minimal memory footprint, before I got used to Clojure.
So Clojure has made me a fan of lazy evaluation, even in Java.
Regarding item 1, one of my friends is a professor and tries to fund a student to help with making Clojure stack traces more understandable. I will not say who that friend is and what university or college s/he is in (s/he has not authorized me to say this), but if anyone thinks they can help with funding I will contact the said friend. Thanks!
> 2. ubiquitous laziness can lead to some really subtle bugs
After the recent compiler change to prevent accidental head retention of lazy sequences, I don't remember having faced any subtle issue with laziness. Can you give me an example of what bit you?
I wish someone would take the compiler infrastructure of Go and would make native Clojure with it, with an easy access to C instead of Java. I need a good exit path from things like Java, not something to just ease the pain.
That is a nice idea. Another way to reach the goal of an alternative native (non-JVM) Clojure would be to build something on top of Racket or Gambit-C Scheme.
BTW, my favorite aspect of Clojure is the common "seq" API for lists, vectors, maps, trees, etc.
Great article overall, but it makes the same mistake as many other Clojure overviews: implying that STM is the only means of managing state. Clojure, in fact has four main ways to do state, one of which is a (thread-local) normal variable. Each is appropriate for a different sort of stateful operation; STM is the most complicated.
It is not a great article overall. It is well written, and conveys a lot of enthusiasm, but has no insightfull/new content in it. I've read every clojure news and article for six months, and this just basically rehashes every "I love clojure article" i ever read.
I agree with the article, and I have to admit I think Rich Hickey (creator of Clojure) is a brilliant man. If you check into his thoughts on programming you will find some very interesting arguments. His talk on state and identity: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hic... is awesome, and I can not recommend highly enough.
If you want motivation for learning a lisp (Clojure is one) check out http://www.paulgraham.com/avg.html if you have not already done so. An awesome essay to re-read if you have not done so in a while.
Can you explain the point he is making in "Are we there yet"? I have watched it but I didn't really get a different viewpoint on state and identity. That could be because I already had the same viewpoint, but I doubt that.
Not sure I'll have time to check out Clojure any time soon, but this post convinced me I want to read SICP. Despite hearing great things about it, my impression was always that it was much better for beginners, and wouldn't teach me that much. Sounds like I was wrong.
Excellent. Since picking up (and falling in love with) Clojure a few months ago, I've had multiple "Why Clojure?" discussions with friends and co-workers. This post is short, sweet, and hits all the points I've tried to make (poorly) to others. Saving it now as ammunition for the next "Why Clojure?" discussion :)
I will be forever grateful, that my University taught Scheme/Lisp with this book (and others) as introduction to programming.
While I have never used Lisp or Scheme in my professional life, that set of undergrad courses more or less defined my mindset when it comes to algorithms and their expression and has lasted to the present day (some 20 years later).
Agreed. I went to the University of Minnesota which modeled its curriculum after the MIT CS program. I was saddened to hear they were ditching Scheme for their intro class. I don't see why they felt the need to update to a more "modern" language. It's impossible for any language to ever more directly express the basic concepts of functions and recursion than lisp. Why muddy the waters with syntax?
I guess there's an established trend how one writes about switching to new language: it's usually a long blog post containing facts distilled by others, sometimes mixed with author's wishful thinking. All that because author probably feels a need to justify his decision.
It's normal - we usually want to justify the reasons why we do stuff, esp. when the new way is time consuming. It's also great that the OP is willing to dive into new waters. But such article cannot be taken as an expertise, even for the reason that it's not from OP's experience (yet).
A more complete and detailed answer to this article's question is provided by the free Chapter 1 of Amit Rathore's book-in-progress, Clojure in Action:
As Rathore puts it, Clojure's power is drawn from three mutually supportive design decisions: 1) it's a Lisp, 2) it's functional, and 3) it's on the JVM. Read Chapter 1, it's well written.
I've never more than dabbled in the functional programming world. I've been pretty happy professionally in Ruby for the last 5 years. However, if there's one thing that I learned, it's that unit testing is an invaluable sanity check but a poor substitute for mathematical rigor.
I see my trajectory over the next 5 years to involve learning Haskell well enough to know the functional approach for a much wider set of problems, but then falling back to Clojure professionally because, you know, I gotta get shit done.
Anyone have any recommendations for trying Clojure? I'm an Emacs user on Ubuntu and I'd like to try it out but there seems to be quite a lot of choice about how you do things I'm a bit lost.
Any up to date blog posts on setting up Clojure and connecting Slime to it? The ones I've found are always slightly out of date (apparently starting swank from Emacs isn't the preferred way to do it anymore?)
Yeah there are a bunch of different ways to start Clojure with a REPL and/or swank server running. Maven, Leiningen, and cake are all build tools that also do dependency management - great when you're working on a complex project but have some amount of setup overhead for their project descriptors. cljr is a different option that lets you start a REPL anywhere, with no project descriptor, and also takes care of setting up your JVM classpath with any dependencies you've installed via 'cljr install'.
All of these tools encourage running the JVM outside of emacs, rather than as an inferior-lisp, and have some command line option that starts a swank server on a specified port. After that you can just do M-x slime-connect and get hacking as usual =)
Swank Clojure is a server that connects SLIME and Clojure projects. Its github page has instructions on installation and usage, hopefully that will serve as a good starting point:
There is a lot of bad out-of-date documentation out there, but I like to think the official docs are pretty serviceable; if they aren't please help point out how.
> become enamored with a language that has roots that go back to 1957, i.e. Lisp?
Duh. What does that punk think that the "60" in Algol 60 stands for? Y'know, the bondage and discipline languages also have an ancestry that goes pretty far back.
And I'd choose C++ (or Java) over Algol just as I'd choose Clojure over Lisp1.5 any time.
...any time a Clojure programmer want's to change the state of a variable, they must do so using the same kind of transaction management as they would use for a database.
Not a good thing. The word 'must' is the glaring red flag.
And it's as simple as e.g. (dosync (ref-set ref newval)). In fact, if you find yourself doing it a lot (don't, please!) then define yourself a little function (defn rset [r v] (dosync (ref-set r v))).
Must isn't that bad of a word, and it's a Lisp: what kind of boilerplate do you expect to write? I prefer it going on none.
It's definitely worth checking out, and if you need state, and you'll need it rarely if at all, you're better served using the built-in STM and the wonderful functions that allow you to manage it (like add-watch; what a lifesaver in a state-heavy app like a GUI) to handle the mess.
unless things have changed dramatically since earlier this year you can have a mutable cell called an 'atom' if you want. it will almost inevitably be a reference to an immutable data structure but it behaves just like any other mutable cell, and does not have to be wrapped in a transaction.
besides, i think even truly single-assignment languages seem to have a place, just ask those crazy erlang guys ;)
the way i read clojure's philosophy around state is: "you can fuck up the concurrency if you want but we're going to make it really hard to do it by mistake".
One thing others haven't mentioned, you still have the option of creating a normal java object and manipulating it with the standard method accesses. Those aren't forced to be immutable by Clojure. Fortunately doing that makes it fairly obvious what you're doing since it won't look like seq accesses, creating a code smell so you can decide if you're doing it too much as you get better with the language.
It's not strictly correct. You define variables all the time via vars. You must in the sense that if you want to do anything over time, since doing it other way is insane.
It's not totally true, either; there are other ways to do state in Clojure. But none of them simply let the programmer, you know, change the state of a variable.
Hey, what's wrong? It is so cool and modern Lisp implementation which runs on even more cool and super-efficient JVM (who said Ernang?!), so, why not?! Let's port HN news app to Clojure and see how much users it can handle. Every one know that Jetty is so cool! ^_^
[+] [-] Raphael_Amiard|15 years ago|reply
> Functional programming, of the kind shown in SICP, is a way to write code that does not manage the state of variables, and could therefore be partitioned to run in parallel on as many processors as you like
This is kind of true, but totally misleading, because very few tasks are actually easily paralelizable this way. When you stumble on one, you know it, and replacing map with pmap certainly is a joyful exercise, but this kind of parallelization are easy to do in any languages. The hard parts are those when you need to access shared state across threads. The facilities that clojure provide in this respect, while innovative and enlightening , have benefits that largely remain to be proven.
> languages like F# and Scala which have a complexity and "quirkiness" reminiscent of C++
Erm, sorry, what, F# reminiscent of C++, did you even try to read some code written in F# ? F# has one of the tersest syntax you're likely to find in any language. As an ML descendant it does already have a very clean syntax, and the addition of significant whitespace only adds to that.
> You can write Clojure code that derives from Java classes and overrides Java methods. In short, if you can do it in Java, you can do it in Clojure.
Yeah sure, but in practice, most people that says that didn't ever had to really handle a non trivial project with java interaction in it. I did. And frankly it can get ugly. It's good to have it, but ideally, all should be encapsulated in idiomatic clojure wrappers. While this is not that hard because java interaction is very well thought, it's a long and boring process, and when you're in the middle of a project and just needs some bit of functionnality that isn't in a clojure lib (and trust me there are still a lot of those), you tend to just use the java interop in place. And then you get back and read your code, and you cry.
In short, this is just a rehashing of what you usually hear about clojure, but with no insight of real use. My (uninformed) guess, is that the author probably didn't use clojure a lot, and frankly, this kind of stereotyped talk gets old.
[+] [-] swannodette|15 years ago|reply
> but this kind of parallelization are easy to do in any languages.
Not if you have a GIL. Even then the languages without that limitation do not make what pmap does ... easy.
> [STM] have benefits that largely remain to be proven.
I always find this statement to be misleading. STM has been shown to greatly benefit the correctness of concurrent programs, you're managing that less by hand. The only thing that seems to be unproven is whether the performance tradeoff is worth it. It'd be nice to see some numbers that show what you lose in X% of the performance vs removing X% the amount of locking code.
> [Java interop] And frankly it can get ugly. It's good to have it, but ...
Yet far less tedious and simpler than writing a C module, or a C library binding. If you're comparing against that, Clojure's Java interop story is damn heavenly.
> In short, this is just a rehashing of what you usually hear about clojure, but with no insight of real use ...
Perhaps for you and I. But there are a lot of people in this big wide world. Uncle Bob taps into a community that's quite different from the language enthusiast crowd of HN.
Your viewpoint more myopic than the OP. Yet you get upvotes. Oh well.
[+] [-] Dn_Ab|15 years ago|reply
1) Functional languages makes parallel programming magically easy.
This is something that is misleading as you point out. Functional languages (where you have not used mutable state) do make it easy to convert you algorithm to run on multiple cores but that doesn't translate to an algorithm that scales well with number of cores. The problem of parallelization is not one of syntax or even semantics, it is an algorithmic one. You need to have in mind the problem and how to make it scale. Just cause you didn't use state doesn't mean that the algorithm that you wrote automatically takes full advantage of parallelism to solve a problem.
What functional programming does is allow you to more easily express the parallel algorithm when you have it as well as giving you more options in how to do so. But for now and maybe this is cultural inertia, coming up with parallel algorithms is hard regardless of language. This is a distinction that is often glossed over probably because those who are aware of it find it so basic as to not worth mentioning.
2) F# and Scala are quirky and complex
I will give a disclaimer and say that I use F# to write machine learning stuff so I am likely extra sensitive to this kind of bashing but..
That statement makes no sense and has no real meaning. Does he mean that the semantics allow undefined behaviours ala C++ or that the syntax is overly verbose or the syntax is just plain confusing? F# syntax is not so far from ML or Haskell or even python. As for undefined behaviour, strongly I doubt that applies. Scala has a formal specification. While F# doesn't have a formal specification it does have a very thorough (good enough) informal one. I am certain that it will not have implementation dependent behaviour and its strong static type system and garbage collected nature precludes the chance for un-trapped errors so the C++ style undefined behaviour can't be the issue.
F# is certainly not verbose and although Scala, being more OOP centric is a bit more wordy, both languages are quite expressive. Terse syntax is meaningless. What matters is how easy and quickly it is to correctly express an algorithm balanced with how easy it is to mentally uncompress it later (on this case F# may even sometimes be too terse! I have taken to commenting and using quite long names for complex algorithms since otherwise it takes a goodly number of minutes to decompress - especially when the code is littered with single letter variable names that the mathematics like syntaxes subconsciously promote). I will admit that where F# is clunky is the number of ways you can cast and it is a fairly big language with Active Patterns, Workflows and Async and Agents on top of the typical functional idioms. But each such feature transfers a lot of expressive power - a fair trade.
To brush aside languages like Scala , F# without having spent much time on them and in such an ambiguous manner is simply not fair. It is okay that he chose Clojure (wonderful language) but did not have the time (measured in months - fair enuff) to properly investigate all the choices but to brush them aside so trivially is intellectually dishonest, to be brutally truthful.
[+] [-] cageface|15 years ago|reply
1. stack traces are very hard to decipher
2. ubiquitous laziness can lead to some really subtle bugs
3. the syntax can be extremely obtuse, moreso than other lisps
4. the basic ADT is just a keyed map, which provides a lot of flexibility but also can make data modeling very opaque, even compared to other dynamic languages
5. immutable and recursive as a default takes a lot of getting used to. things I could dash out in minutes in ruby take me hours sometimes
6. other languages have caught up enough that Lisp macros are not as game changing as they might have been ten years ago
I embarked on a project recently to explore machine learning algorithms, implementing them in both Scala and Clojure at the same time. I expected this to be an easy win for Clojure but, to my surprise, I'm much more productive in Scala, my code has fewer bugs, and I can refactor it much more aggressively. I realize that this isn't an either/or thing and it may be entirely my shortcomings at play here, but my instinct is that although Clojure is a superb lisp, it's still a lisp, and it's going to be a niche that most programmers won't choose to occupy.
[+] [-] swannodette|15 years ago|reply
2. Mutable state can lead to really subtle bugs
3. Sure but no more than Haskell or any other terse FP lang, Scala included
4. defrecord works wonders. You get all the flexibility of a map with the context of an actual type
5. It takes me hours to do things in Ruby that I could dash out in Clojure.
6. Right.
Quite a few people in the Clojure have come from Scala. So everyone is entitled to their own opinion.
[+] [-] jimbokun|15 years ago|reply
I find myself implementing Iterable wrappers more often in Java now, largely due to the influence of Clojure lazy seqs. Then I can use the abbreviated for loop syntax, for example, without creating a ridiculously large ArrayList in memory.
I know that the Iterator pattern has been around for a long time, but I never realized how broadly it could be applied to use high level iteration constructs while keeping a minimal memory footprint, before I got used to Clojure.
So Clojure has made me a fan of lazy evaluation, even in Java.
[+] [-] cema|15 years ago|reply
[+] [-] crc|15 years ago|reply
After the recent compiler change to prevent accidental head retention of lazy sequences, I don't remember having faced any subtle issue with laziness. Can you give me an example of what bit you?
[+] [-] Dn_Ab|15 years ago|reply
[+] [-] mhd|15 years ago|reply
[+] [-] bitdiddle|15 years ago|reply
[+] [-] silentbicycle|15 years ago|reply
Chicken Scheme is good, too.
[+] [-] mark_l_watson|15 years ago|reply
BTW, my favorite aspect of Clojure is the common "seq" API for lists, vectors, maps, trees, etc.
[+] [-] dmaclay|15 years ago|reply
[+] [-] Zak|15 years ago|reply
[+] [-] Raphael_Amiard|15 years ago|reply
[+] [-] nkh|15 years ago|reply
If you want motivation for learning a lisp (Clojure is one) check out http://www.paulgraham.com/avg.html if you have not already done so. An awesome essay to re-read if you have not done so in a while.
Edit: Fixed Link (thanks atuladhar)
[+] [-] jules|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] edanm|15 years ago|reply
[+] [-] zsouthboy|15 years ago|reply
Wanted a deadtree version to read at my leisure, but at $70 I think I'll read the HTML version.
EDIT: found a PDF version: http://www.scribd.com/doc/15556326/Structure-and-Interpretat...
[+] [-] mattwilliams|15 years ago|reply
http://www.youtube.com/watch?v=mslMLp5bQD0
[+] [-] bitsai|15 years ago|reply
[+] [-] linuxhansl|15 years ago|reply
While I have never used Lisp or Scheme in my professional life, that set of undergrad courses more or less defined my mindset when it comes to algorithms and their expression and has lasted to the present day (some 20 years later).
[+] [-] dasil003|15 years ago|reply
[+] [-] kunley|15 years ago|reply
It's normal - we usually want to justify the reasons why we do stuff, esp. when the new way is time consuming. It's also great that the OP is willing to dive into new waters. But such article cannot be taken as an expertise, even for the reason that it's not from OP's experience (yet).
[+] [-] limist|15 years ago|reply
http://www.manning.com/rathore/
As Rathore puts it, Clojure's power is drawn from three mutually supportive design decisions: 1) it's a Lisp, 2) it's functional, and 3) it's on the JVM. Read Chapter 1, it's well written.
[+] [-] dasil003|15 years ago|reply
I see my trajectory over the next 5 years to involve learning Haskell well enough to know the functional approach for a much wider set of problems, but then falling back to Clojure professionally because, you know, I gotta get shit done.
[+] [-] gaius|15 years ago|reply
[+] [-] almost|15 years ago|reply
Any up to date blog posts on setting up Clojure and connecting Slime to it? The ones I've found are always slightly out of date (apparently starting swank from Emacs isn't the preferred way to do it anymore?)
[+] [-] arete|15 years ago|reply
All of these tools encourage running the JVM outside of emacs, rather than as an inferior-lisp, and have some command line option that starts a swank server on a specified port. After that you can just do M-x slime-connect and get hacking as usual =)
[+] [-] bitsai|15 years ago|reply
http://github.com/technomancy/swank-clojure
[+] [-] technomancy|15 years ago|reply
If there is something that's not covered or linked to by that post, please submit a bug report to Swank-Clojure: http://github.com/technomancy/swank-clojure/issues
There is a lot of bad out-of-date documentation out there, but I like to think the official docs are pretty serviceable; if they aren't please help point out how.
[+] [-] sqrt17|15 years ago|reply
Duh. What does that punk think that the "60" in Algol 60 stands for? Y'know, the bondage and discipline languages also have an ancestry that goes pretty far back.
And I'd choose C++ (or Java) over Algol just as I'd choose Clojure over Lisp1.5 any time.
[+] [-] jules|15 years ago|reply
[+] [-] herdrick|15 years ago|reply
Not a good thing. The word 'must' is the glaring red flag.
[+] [-] ihodes|15 years ago|reply
And it's as simple as e.g. (dosync (ref-set ref newval)). In fact, if you find yourself doing it a lot (don't, please!) then define yourself a little function (defn rset [r v] (dosync (ref-set r v))).
Must isn't that bad of a word, and it's a Lisp: what kind of boilerplate do you expect to write? I prefer it going on none.
It's definitely worth checking out, and if you need state, and you'll need it rarely if at all, you're better served using the built-in STM and the wonderful functions that allow you to manage it (like add-watch; what a lifesaver in a state-heavy app like a GUI) to handle the mess.
[+] [-] benreesman|15 years ago|reply
besides, i think even truly single-assignment languages seem to have a place, just ask those crazy erlang guys ;)
the way i read clojure's philosophy around state is: "you can fuck up the concurrency if you want but we're going to make it really hard to do it by mistake".
[+] [-] runevault|15 years ago|reply
[+] [-] KirinDave|15 years ago|reply
[+] [-] herdrick|15 years ago|reply
[+] [-] inodeman|15 years ago|reply
[deleted]
[+] [-] c00p3r|15 years ago|reply
[+] [-] c00p3r|15 years ago|reply
[+] [-] jsmcgd|15 years ago|reply
[+] [-] knodi|15 years ago|reply