News for hackers. Stuff that matters.
Re:The Beauty of Clojure by nnq on Wednesday August 26, 2015 @02:56AM (#10121492)
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_soft...)

...really, people, stop scaring learners away!

Re:The Beauty of Clojure by hellofunk on Wednesday August 26, 2015 @03:34AM (#10121617)
Because -> 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.
Re:The Beauty of Clojure by owen4d on Wednesday August 26, 2015 @03:42AM (#10121645)
Ha, 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.

Re:The Beauty of Clojure by fnordsensei on Wednesday August 26, 2015 @04:04AM (#10121711)
Good 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.
Re:The Beauty of Clojure by hohenheim on Wednesday August 26, 2015 @04:47AM (#10121810)
This 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.
Re:The Beauty of Clojure by jffry on Wednesday August 26, 2015 @08:16AM (#10122371)
For 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
Re:The Beauty of Clojure by icebraining on Wednesday August 26, 2015 @05:50AM (#10121987)
As 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.
Re:The Beauty of Clojure by grayrest on Wednesday August 26, 2015 @09:21AM (#10122666)
If it's particularly confusing you can always use swiss arrows[0] instead:

   (-<> (range 10)
        (map #(+ % 2) <>)
        (reduce + <>))

[0] https://github.com/rplevy/swiss-arrows

It's more common in functional languages and called a thrush or pipe operator.

F#:

    [|0..9|] |> Seq.map ((+) 2) |> Seq.sum
Javascript (Ramda):

    R.pipe(R.range(0,10), R.map(R.add(2)), R.sum)();

    //With slightly more magic
    let {pipe, range, map, add, sum} = R;
    pipe(range(0), map(add(2)), sum)(10);
Re:The Beauty of Clojure by icebraining on Wednesday August 26, 2015 @10:31AM (#10123113)
While they might make the flow clearer, I don't think the swiss arrows fix what I perceive as more confusing for a newcomer.

The problem is that -<> looks like a regular function call, but does things that a function call can't do. In a language without macros, which are most of the mainstream ones, <> would have to be a language feature, and then it's not clear why you'd need to use -<> to 'activate' it.

Now, I've read enough about Lisp and AST and such to understand what a macro is, but the concept doesn't map easily to mainstream languages.

Re:The Beauty of Clojure by danneu on Wednesday August 26, 2015 @03:48PM (#10125558)
Clojure's standard library already has a threaded placeholder:

    (as-> (range 10) _
      (map #(+ % 2) _)
      (reduce + _))
Re:The Beauty of Clojure by jdd on Friday August 28, 2015 @07:57PM (#10138414)
JavaScript (lodash-fp):

    _.flow(_.range(0,10), _.map(_.add(2)), _.sum)();

    //With slightly more magic
    let {flow, range, map, add, sum} = _;
    flow(range(0), map(add(2)), sum)(10);
Re:The Beauty of Clojure by nnq on Wednesday August 26, 2015 @09:13AM (#10122628)
...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

(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" :) )

Re:The Beauty of Clojure by icebraining on Wednesday August 26, 2015 @10:19AM (#10123019)
But (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.
Re:The Beauty of Clojure by AnimalMuppet on Wednesday August 26, 2015 @01:17PM (#10124508)
No (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...)

Re:The Beauty of Clojure by icebraining on Wednesday August 26, 2015 @01:35PM (#10124649)
(Or were you talking about the "." as used in OO, compared with the "->" as used in Clojure? If so, disregard this comment...)

I'm afraid I was :)

Re:The Beauty of Clojure by kazinator on Wednesday August 26, 2015 @10:50AM (#10123262)
Why 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.

Re:The Beauty of Clojure by logarhythm on Wednesday August 26, 2015 @03:42AM (#10121647)
Totally 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 +).
Re:The Beauty of Clojure by alexott on Wednesday August 26, 2015 @03:40AM (#10121633)
only 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)
Re:The Beauty of Clojure by agumonkey on Wednesday August 26, 2015 @02:57AM (#10121496)
First principles I guess, although I sure love `->` and its siblings.
Re:The Beauty of Clojure by nnq on Wednesday August 26, 2015 @03:04AM (#10121514)
If 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/ :)

Re:The Beauty of Clojure by kaonashi on Wednesday August 26, 2015 @11:18AM (#10123463)
McCarthy had something to say about this... http://www-formal.stanford.edu/jmc/recursive.pdf
Re:The Beauty of Clojure by agumonkey on Wednesday August 26, 2015 @03:39PM (#10125499)
Which paper is the one with the symbolic differentiator ?
Re:The Beauty of Clojure by agumonkey on Wednesday August 26, 2015 @05:11AM (#10121893)
Recursive 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).
Re:The Beauty of Clojure by nnq on Wednesday August 26, 2015 @09:06AM (#10122591)
EDIT: 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 +)`
Re:The Beauty of Clojure by VladimirGolovin on Wednesday August 26, 2015 @08:31AM (#10122439)
I'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])
Re:The Beauty of Clojure by vzcx on Wednesday August 26, 2015 @08:41AM (#10122472)
Mostly, but I'm pretty sure Clojure's range gives the integers from 0 to 9.
Re:The Beauty of Clojure by platz on Wednesday August 26, 2015 @12:09PM (#10123903)
pretty much almost all folds in strict languages can be assumed to be left folds.
Re:The Beauty of Clojure by tel on Wednesday August 26, 2015 @08:37AM (#10122459)
Yep!