6
$\begingroup$

As an exercise, I was trying to convert the following Clojure code to Mathematica:

user=> (->> (range)
            (map #(* % %))
            (filter even?)
            (take 10)
            (reduce +))
1140

I got partway with this code in which I wanted to use the postfix version of the corresponding functions in order to have the same reading of the functions as with Clojure's threading operator:

Range@20-1 // Map[#*# &] // Select[EvenQ[#] &] 

I was stuck with the reduce because in trying to apply the equivalent Take and Fold I found out there's no operator form of these functions and so I couldn't use them in postfix form. Is there some alternative way to get the same left-to-right sequence of functions as with Clojure?

For those not familiar with Clojure, here's a brief explanation of the threading operator ->> where I obtained the sample above. You can also find help and examples for the other functions at that link. Note that other than reduce (Fold in Mathematica) and filter (Select in Mathematica), the other Clojure functions have the same name as their Mathematica equivalents.

The #(* % %) is a lambda function (pure function as Mathematica calls them) and is equivalent to #*# &.

$\endgroup$
1
  • 3
    $\begingroup$ You can use any function in postfix form if you just make a pure function out of it, as you seem to be comfortable doing, like // Fold[Plus, #] & $\endgroup$
    – Jason B.
    Apr 29 '16 at 7:45
5
$\begingroup$

Since any function in Mathematica can be used in postfix form by appending & to make it a pure function, the following code can be used:

In[39]:= 20 // Range[#]-1 & // Map[#*# &] // Select[EvenQ] // Take[#, 10] & // Fold[Plus, #] &

Out[39]= 1140

Alternatively, Total or Apply[Plus] could be used instead of Fold[Plus, #] &; Fold is just the closest analog to Clojure's reduce.

The above doesn't exactly mirror the Clojure code since the upper limit for the range has to be specified in the Range call as there is no zero argument variant of Range in Mathematica. In Clojure, range without an argument returns a lazy sequence of 0 up to infinity which is determined only when the final expression is evaluated.

To get the first 10 even squares, we need to start with at least double that number and subtract 1 in order to match the 0 starting point of the Clojure range.

$\endgroup$
5
  • 2
    $\begingroup$ Downvote for un-truth ("...does not have an operator variant so that it can't be used in postfix form"): {1, 2, 3, 4, 5} // Take[#, 3] & $\endgroup$
    – LLlAMnYP
    Apr 29 '16 at 8:34
  • $\begingroup$ Thanks, I didn't know; updated answer to take this into account. $\endgroup$
    – Adrian
    Apr 29 '16 at 13:17
  • $\begingroup$ Right,downvote reverted. Instead of folding plus you could just use Total. $\endgroup$
    – LLlAMnYP
    Apr 29 '16 at 13:33
  • 1
    $\begingroup$ Lazy lists are implementable in MMA, see mathematica.stackexchange.com/a/885/26956 $\endgroup$
    – LLlAMnYP
    Apr 29 '16 at 13:41
  • 2
    $\begingroup$ FYI: Select[EvenQ[#] &] may be replaced with Select[EvenQ] $\endgroup$
    – Mr.Wizard
    Apr 30 '16 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.