What does this function definition do in the clojure code example?

I follow โ€œClojure in actionโ€ and I am confused by this:

(defn with-log [function-to-call log-statement ] (fn [& args] (println log-statement) (apply function-to-call args))) 

This is the code segment that confuses me. This is what I can still decrypt:

(defn with-log [statement-function-to-call-operator] ..) defines a function called "with-log" that accepts function-to-call and logical operator arguments and the -to-call function - it is a function passed as a parameter to this function. The following section confuses me: (fn [& args] .... is the anonymous function defined here? Does the 'with-log' function return a new function definition?

 (fn [& args] (println log-statement) (apply function-to-call args)) 

So calling (with-log somefunc "my shortcut") is it just saving a new anonymous function? Or does it call an anonymous function?

+4
source share
3 answers

with-log will give a function that, when called, will do exactly what function-to-call did, except with the side effect that the log-statement will be printed on *out* just before function-to-call is evaluated with using the arguments of a given anonymous function.

This is an example of a Decorator Pattern - extending the behavior of an existing function by transferring it to another function, that is, an anonymous function created with-log using the form (fn ...) .

In order for the with-log decorator function to work with any conceivable function-to-call , the list of anonymous function arguments is defined so that it can be called with the number of arguments using (fn [& args] ...) . When an anonymous function calls function-to-call , it expands the argument list using the apply function).

Ways to use with-log can be:

 ((with-log some-fn "Calling some-fn") arg1 arg2) 

or

 (defn my-fn [ab] (+ ab)) (def my-fn-with-logging (with-log my-fn "Calling my-fn")) (my-fn 1 2) ; evaluates to 3 (my-fn-with-logging 1 2) ; prints "Calling my-fn" and evaluates to 3 
+6
source

It returns an anonymous function, and it is not called.

For example, this will call an anonymous function with the given arguments:

 ((with-log some-fn "log statement") arg1 arg2) 

This works because the returned function is the first element in the list, which means that it is called just like any other function.

+1
source

Yes you are right. (fn ..) is a form that creates an anonymous function. This piece of code, given by the function f and some value of s , will return a function that, when called, will print s , and then call f :

 user=> (defn with-log [function-to-call log-statement ] (fn [& args] (println log-statement) (apply function-to-call args))) #'user/with-log user=> (with-log + "String") #<user$with_log$fn__1 user$with_log$fn__1@147264b1 > user=> ((with-log + "String") 1 2 3) String 6 user=> 

Note the line starting with #<user$... This is the internal identifier of the anonymous function that has just been created, i.e. A simple call with-log returns a function. And then we use the same function (it is similar in its behavior, it will be a different object in fact, because each call to with-log creates a new "instance" of the same function) for several arguments. The string "String" is printed, and then REPL shows us the result (+ 1 2 3) .

Here you can find out more about this.

0
source

All Articles