4 ms·
I think you may be misunderstanding a few things, and I hope I can clear them up :) First, the term "pure function" does not imply "ivory tower" any more than "
by nonrecursive 12y ago
I think you may be misunderstanding a few things, and I hope I can clear them up :) First, the term "pure function" does not imply "ivory tower" any more than "recursion" does. Pure functions are tools that allow you to "isolate mutation". In fact, Paul Graham mentions that experienced lisp programmers "try to segregate side-effects in a few functions, allowing the greater part of the program to be written in a purely functional style" (http://unintelligible.org/onlisp/onlisp.html#SEC27 http://unintelligible.org/onlisp/onlisp.html#SEC27). So - don't let the terminology throw you :)
Second, the point of the point of the chapter is to show how much can be accomplished without mutating data structures. I think that's something valuable to focus on. Saying "You can do a lot with pure functions and immutable data structures" is not the same as saying "You'll never need to mutate anything" and as the author, I apologize if my writing suggests otherwise :(
Lastly, Clojure definitely places a huge emphasis on limiting mutability by using pure functions and immutable data structures. I think Rich Hickey even describes pure functions as stable bricks or stable atoms in one of his talks. My impression is that it's definitely not the love child of common lisp and java. Clojure is pragmatic, but that doesn't mean it doesn't place an emphasis on functional programming. I agree that it's "not bogged down in a theory of pure anything", but that doesn't mean it wasn't intentionally designed to support and encourage programming with pure functions and immutable data structures.
- brudgers 12y agoThe article well written. It didn't throw me or make me confused. I simply was bothered by the lack of nuance in regard to mutation. Trillions of pixels have been burned describing pure functions and giving small examples of immutability and recursion. Trees have even been killed. What makes Chapter 3 of On Lisp or SICP useful is they're Third Acts. They go deeper than pure functions. They're pivotal because that's where we start talking about the messy world where mutation is necessary. It's where we admit that there's a rationale for the way Java works even if it's implementation could stand improvement. What makes Clojure interesting is the way in which it implements that depth. Lisp went on a journey to Java and was transformed by the experience. Clojure is not just another Lisp - that side of the family has always had shared structure and a propensity for functions. There's `is` and 'testing` and agents and vars and `.` and `..`. JavaScript the good parts is a book. Java the good parts are in Clojure. Clojure is an Act V not an Act I.
- nonrecursive 12y agoThe book chapter aside, I think you might actually have it backwards. Hopefully I'm not misunderstanding you terribly! The reason why PG has to spend as much time as he does warning programmers about hidden ways in which Common Lisp mangles your data structures (nconc, for example) is because Common Lisp does not come with immutable data structures out of the box. My impression is that he's telling you how to work as well as you can (strive for purely functional code) with the tools at hand. Clojure, on the other hand, was built so that you could code without having to worry about that stuff by default. Also, you say that lisps have "always had shared structure." I'm not sure what you mean by that? Clojure implements _structural sharing_, which is what allows it to have persistent, immutable data structures. Common Lisp certainly doesn't do the same. I'm not sure what you mean by "Lisp went on a journey to Java and was transformed by the experience." I think you're saying that Rich Hickey designed Clojure to be a lisp that's more Java-like? Could you explain how? My impression is that Rich Hickey thinks OO is broken (see the talk "Are we there yet?"), as is the notion of mutability as implemented by Java. Clojure's interop with Java is a great convenience, but the emphasis is still on functional programming. I don't think I understand what you're saying, or maybe it's just that we disagree? Finally, from clojure.org: "Clojure is predominantly a functional programming language, and features a rich set of immutable, persistent data structures. When mutable state is needed, Clojure offers a software transactional memory system and reactive Agent system that ensure clean, correct, multithreaded designs." Maybe it's these state management features you're concerned about? If so, then I would suggest that vars, atoms, refs, and agents are not as inspired by Java as you're saying. Or maybe we just disagree that, the majority of the time, you should be writing pure functions and using immutable data structures in Clojure?
- brudgers 12y agoPG isn't warning any experienced Common Lisp programmer about `nconc`. The [n] at the front means it's destructive...there's also `nsubst` and `nreverse` and `nstring-capitalize`. They all exist in Common Lisp to allow a programmer to avoid consing and the subsequent garbage collection. In other words, they exist to allow a programmer to optimize their code. They exist as exceptions to idiomatic Common Lisp practice of returning values in lieu of mutating locations. Sure it is not as idiomatic in Common Lisp as in Clojure in part because Common Lisp is largely a product of its time and that time was largely single threaded. Avoiding mutation in Common Lisp is even less idiomatic than it is in Scheme - where there are not destructive versions of various functions by default and idiomatic practice is mutation is signaled with a bang [!]. But again, the preferred approach is persistence and writing side-effect free functions. Indeed at the front edge of Scheme, Racket implements immutable data structures by default. Idiomatic functional style and defaulting to immutable data structures are not what makes Clojure unique as a Lisp - it's knob twiddling, not a new paradigm. It has some great built in syntax that allows for the best part of Lisp-2 programming - i.e. symbols representing a collection acting as functions over the collection and the association of a meta-data map with a symbol like a plist. But it's evolutionary as a Lisp. On the other hand, though not unique, idiomatic functional style and defaulting to immutable data structures are unusual in relation to the Java platform. Its relationship to the Java platform is what makes Clojure unique. STM is not a product of it's Lisp heritage. Neither is it's implementation of objects with via interop [largely eschewing objects despite availability is also idiomatic Lisp]. Understand, I'm writing to think. What you've written is just a starting point I can use as an excuse for saying what I was primed to say anyway. Like I said in my original comment, I was already drinking from the Clojure firehose. So what's the upshot? Well what did your article say that hasn't already been said before about functional programming? Why not point people to Chapter 3 of Graham? It's more convincing for those who need convincing and more in depth for those who don't. Why not point people to The Value of Values, it's again more convincing for tire-kickers; a comfortable sermon for the newly converted, and a reference point for those already in the cult. What really makes Clojure unique?