Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure -- what is the correct way to apply functions in sequence to an argument?

Tags:

clojure

I'm not clear on the difference between -> and ->> in Clojure: from the API reference, it seems like the latter would be the correct way to apply several functions in sequence, i.e. (->> x h g f) would result in f(g(h(x))).

This is related to how Lisp-like language differentiate f(x, y) and (f(x))(y), whereas Haskell does not, correct? (Using math notation; commas intended to imply n-ary functions, not tupling).

Thanks in advance!

Edit

I'm wrong, neither work except on simple functions like (def inc #(+ 1 %)), where they both work.

Here's an example of a function that doesn't work with -> or ->>,

(defn mkinc­ [amnt­] (fn [x] (+ x amnt)­))
(-> 3 (mkin­c 2))
; ERROR -- Wrong number of args (2) passed to: sandbox58780$fn--58797$mkinc
((mkinc 2) 3)
; 5
like image 881
gatoatigrado Avatar asked Jun 16 '11 02:06

gatoatigrado


People also ask

Does it matter what order you put the arguments in to call a function?

Yes, it matters. The arguments must be given in the order the function expects them.

What is the syntax for a function with arguments?

When one piece of code invokes or calls a function, it is done by the following syntax: variable = function_name ( args, ...); The function name must match exactly the name of the function in the function prototype. The args are a list of values (or variables containing values) that are "passed" into the function.

What is FN in Clojure?

Most Clojure code consists primarily of pure functions (no side effects), so invoking with the same inputs yields the same output. defn defines a named function: ;; name params body ;; ----- ------ ------------------- (defn greet [name] (str "Hello, " name) )


1 Answers

-> and ->> are equivalent if all the functions take only one argument. Otherwise, -> passes the value being threaded as the first argument to the function where as ->> passes it as the last argument. The following example should make this clear:

(-> x
    (f 1 2)
    (g 3 4)
    (h 5 6))

becomes

(h (g (f x
         1 2)
      3 4)
   5 6)

or h(g(f(x, 1, 2), 3, 4), 5, 6)

(->> x
     (f 1 2)
     (g 3 4)
     (h 5 6))

becomes

(h 5 6
   (g 3 4
      (f 1 2 x)))

or h(5, 6, g(3, 4, f(1, 2, x)))

Edit: (Responding to the Edit in the question, copying this from the comments).

The example doesn't work because the -> macro inserts the 3 as the first arg of mkinc. See (macroexpand-1 '(-> 3 (mkinc 2))) to understand this better.

This does work: (-> 3 ((mkinc 2))). See (macroexpand-1 '(-> 3 ((mkinc 2)))) to understand why.

like image 64
Siddhartha Reddy Avatar answered Oct 10 '22 05:10

Siddhartha Reddy