5 ms·
I don't get it why Clojure and other Lisp tutorials throw things like this in face of beginners: (reduce + (map (comp inc inc) (range 10))) instead of jus
by nnq 11y ago
I don't get it why Clojure and other Lisp tutorials throw things like this in face of beginners:
(reduce + (map (comp inc inc) (range 10)))
instead of just using things like the "->" macro to make the damn thing just as in any other language:
(-> (range 10)
(map #(+ % 2))
(sum))
...it's as if they purposely try to scare people away from Lisp! Some kind of smug superiority makes them wanna make sure no "lesser mortals" want to touch their beloved language. (The added benefit would be that later you can "blow their minds" but showing them how to write "->" themselves and instantly introduce them to the power of macros!)
This is almost close to showing a code snippet like this to someone trying to learn Haskell:
fix$(<$>)<$>(:)<*>((<$>((:[{- thor's mother -}])<$>))(=<<)<$>(*)<$>(*2))$1
(it only prints the powers of 2, but it was enough to scare some people into calling Haskell “the Taliban version of ML”... http://www.theregister.co.uk/Print/2012/12/21/financial_software_disasters/ http://www.theregister.co.uk/Print/2012/12/21/financial_soft...)
...really, people, stop scaring learners away!
- agumonkey 11y agoFirst principles I guess, although I sure love `->` and its siblings.
- nnq 11y agoIf you start thinking along the lines of first principles you could just as well start with a NAND gate. ..because some people were even smart enough to pull this off: http://www.nand2tetris.org/ http://www.nand2tetris.org/ :)
- agumonkey 11y agoRecursive first principles. I don't think n2t will put the emphasis on that (no offense, I love their work and results, something I wished for years).
- kaonashi 11y agoMcCarthy had something to say about this... http://www-formal.stanford.edu/jmc/recursive.pdf http://www-formal.stanford.edu/jmc/recursive.pdf
- agumonkey 11y agoWhich paper is the one with the symbolic differentiator ?
- hellofunk 11y agoBecause -> is not a typical functional idiom, it's a macro specific to Clojure, and anything you can do with -> you can also do in the standard functional way, and beginners are better served by understanding the way a lisp works rather than only get taught syntactic sugars. Keep in mind that -> as a macro does not evaluate its arguments the way a function does, which complicates the understanding for a beginner tremendously, since Clojure is actually an eagerly-evaluated language.
- alexott 11y agoonly in this case, it should be ->>, because -> inserts argument into first position, but you need it in the last... And you can omit parentheses around functions without additional arguments (sum in this case)
- owen4d 11y agoHa, yeah, I get where you're coming from. And I toyed with putting a threading macro example inline, and in the end put a footnote in instead. My reasoning was that basically, regardless of the threading macros, you are going to have to learn to read/write s-expressions as-is for a couple of reasons: 1. The threading macros won't be the best way forward in all cases. 2. You're going to need to read other people's code, which wasn't using the macros. Overall, I was trying to make the point that it is a real hurdle (at least that's how it felt for me), but worth getting over. As a week or so later, you can read s-expressions with relative ease. That it's worth making the effort, because they are pretty awesome. Maybe I just didn't communicate that very well.
- fnordsensei 11y agoGood point. My code is littered with threading macros all over the place, and it can really reduce ))))))))))) to ). But I wouldn't have been able to use it effectively if I didn't know how s-expressions work.
- logarhythm 11y agoTotally agree with your point, but just a quick note: using the thread-first -> macro won't work in this case, instead you'd use the thread-last macro ->>. Also Clojure doesn't have a sum function, so you'd actually use (reduce +).
- hohenheim 11y agoThis is subjective and dependent on the background. I, as a beginner, found the original expression easier to understand, whereas, the "->" macro rewrite seems puzzling. Specially (map #(+ % 2)) looks as if the values are summed and then % 2 is applies to it.
- jffry 11y agoFor an introduction to absolute beginners it could be something like: (->> (range 10) (map (fn [x] (+ x 2))) (reduce +)) And then later on you can explain the #() shorthand
- icebraining 11y agoAs a Clojure/Lisp beginner, I can't say I agree. I don't know any language that works like your example, except maybe shell script with its pipes. Without variables, that expression just seems too "magical". Nested function calls, on the other hand, are common everywhere.
- nnq 11y ago...that's how chaining method calls end up working in most OO languages (take the Scala example in OP's article). And also in Javascript (I can't remember if there is something like `range` in js right now...): [1,2,3,4,5,6,7,8,9,10] .map(function (x) { return x + 2 }) .reduce(function (a, b) { return a + b }) so the "." in OOP ends up working like "->" or "->>". Heck, you can make the dot in OOP code behave like anything, even like monadic bind (`>>=` or `do` notation in Haskell), if you do OOP-style-monads in JS: https://www.youtube.com/watch?v=b0EF0VTs9Dc https://www.youtube.com/watch?v=b0EF0VTs9Dc (off-topic: this is also my main problem with OOP... the "." can actually end up meaning anything practically, as program logic is concerned, it's like some kind of "infinite operator overloading" :) )
- icebraining 11y agoBut (conceptually) the "." in most OO languages is something that is part of the object it's being applied to, while the -> is something external that one applies to the subsequent expressions. At least, this is what I perceive by looking at the code, and in my opinion, the two concepts don't map intuitively.
- AnimalMuppet 11y agoNo (at least not in one specific OO language, namely C++). "foo->" means exactly the same thing as "(*foo)." That is, you use "." when you have an object, and "->" when you have a pointer to an object. I don't know of any other OO language that uses "->". If there is one, my comments here probably do not apply to it... (Or were you talking about the "." as used in OO, compared with the "->" as used in Clojure? If so, disregard this comment...)
- VladimirGolovin 11y agoI'm new to Clojure and I'm trying to parse this line: (reduce + (map (comp inc inc) (range 10))) Is the following a correct Haskell equivalent? foldr1 (+) (map (succ.succ) [1..10])
- nnq 11y agoEDIT: as observed by others, `->` should actually be `->>`, sorry for the typo, but unfortunately I can't edit the original comment anymore. Also forgot there's no "sum" already defined in Clojure, so replace that with `(reduce +)`
- kazinator 11y agoWhy other Lisp tutorials don't teach -> is, firstly, that other Lisp's don't have that, except as some add-on library feature. Secondly, it's a syntactic sugar that has quite a bit going on under the hood: implicit parameters, a lambda function being expressed as #(+ % 2) with this % thingy, and return values of forms being passed as arguments to other forms that are not syntactically enclosed. You have to understand that (range 10) is just called normally, but then its return value becomes an extra invisible argument to the (map ...) form. Newcomers should learn the underlying ordinary evaluation first.