Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't understand this clojure make-adder example

Tags:

clojure

I'm trying to read up a bit on Clojure, but I hit a brick wall with the following basic example:

(defn make-adder [x]
  (let [y x]
    (fn [z] (+ y z))))
(def add2 (make-adder 2))
(add2 4)
-> 6

What I don't understand is how is add2 passing the number 4 to the make-adder function, and how does that function turn assigns that number to z.

Thanks in advance!

like image 638
Deleteman Avatar asked May 23 '12 13:05

Deleteman


People also ask

What is it like to use Clojure?

It provides the tools to avoid mutable state, provides functions as first-class objects, and emphasizes recursive iteration instead of side-effect based looping. Clojure is impure, in that it doesn’t force your program to be referentially transparent, and doesn’t strive for 'provable' programs.

How do you do arity overloading in CL Clojure?

Clojure supports arity overloading in a single function object, self-reference, and variable-arity functions using &: You can create local names for values inside a function using let. The scope of any local names is lexical, so a function created in the scope of local names will close over their values:

How do you assign function definitions in Clojure?

They can be assigned as values, passed into functions, and returned from functions. It’s common to see function definitions in Clojure using defn like (defn foo …

What is an anonymous function in Clojure?

An anonymous function is a function without a name. In Clojure these can be defined in two ways, fn and the literal # (… ) . Creating a function with defn immediately binds it to a name, fn just creates a function. Let’s have an example with a few music bands:


2 Answers

make-adder returns a function that takes one parameter (z), the parameter passed in to make-adder is used to assign a value to y. add2 is set equal to the result of evaluating make-adder with a parameter of 2. So add2 is set equal to the function returned from make-adder, which (since y has been assigned to the parameter from make-adder) looks like

(fn [z] (+ 2 z))

So (add2 4) calls this function which evaluates to 6. Does that help?

like image 67
Nathan Hughes Avatar answered Sep 21 '22 20:09

Nathan Hughes


To me, it seems you are working on an interesting problem.

Your example make-adder function (rewritten without let bindings)

(defn make-adder [x]
  "Returns a function that returns the sum of x and yet to be supplied z."
  (fn [z] (+ z x))))

returns a function that sums x and z, where make-adder has to have already been called with a value. I believe your example is implementing the Clojure partial function, which is pretty cool.

Here is your make-adder function rewritten to sum its two parameters, and not return a function (so we can use partial in add2),

(defn make-adder
  "Returns sum of x and y." 
  [x y] 
  (+ x y))

and here is add2 rewritten using partial with 2 as the x parameter:

(def add2 (partial make-adder 2))

If I call (add2 2) the answer is 4, (add2 3), the answer is 5 and so on.

like image 43
octopusgrabbus Avatar answered Sep 17 '22 20:09

octopusgrabbus