is this partial function a closure? - clojure

I am discussing closure with a friend and he thinks (partial + 5) is a closure. But I think a closure is a function closing over a free variable, for example
(let [a 10]
(defn func1 [x] (+ x a))
)
then func1 is a closure. But in this case 5 is not a free variable. So which is the right answer?

partial uses a closure to make the partial function. Check out the code of partial by using (source partial) in repl and you will see that it uses closures.
(defn partial
"Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args."
{:added "1.0"}
([f arg1]
(fn [& args] (apply f arg1 args)))
([f arg1 arg2]
(fn [& args] (apply f arg1 arg2 args)))
([f arg1 arg2 arg3]
(fn [& args] (apply f arg1 arg2 arg3 args)))
([f arg1 arg2 arg3 & more]
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))

(partial + 5) is an anonymous function or "lambda".
Anonymous functions are often¹ called "closures" but it's an abuse of the term ; see the discussion in "What is the difference between a 'closure' and a 'lambda'?"
[¹] Maybe because in most popular languages that support them, closures and anonymous functions are created using the same language features - which renders them undistinguishable at first glance.

Related

Clojure: using an If statement as a parameter in a function call, if there are no args, pass nothing

So I have a function do_stuff that can take 0 or 1 arguments as follows
(defn do_stuff
([]
(println "no arguments here"))
([arg]
(println "here's the argument"))
(defn -main
[& args]
(do_stuff (if args (apply str args))
How do I return no argument from the if statement, so that I can print the "no arguments here" string?
Edit: Using the when instead of if returns nil, which is still an argument?
Using multi-arity definitions
Apply the lesson you learned from do_stuff on -main:
(defn -main
([] (do_stuff))
([& args] (do_stuff (apply str args))))
Externalizing condition using if (or cond)
An if expression without else branch still returns nil but returning nil is not returning nothing.
That is you can't make it with an if or when expression that it just returns nothing. At least not in functional languages like Clojure is.
You could alternatively externalize your if like this:
(defn -main
[& args]
(if args
(do_stuff (apply str args))
(do_stuff)))
Using apply
#EugenePakhomov's idea:
(defn -main
[& args]
(apply do_stuff (if args [(apply str args)] [])))
But what I think is: How about to put the (apply str args) part inside do_stuff?
(defn do_stuff
([]
(println "no arguments here"))
([& args]
(let [arg (apply str args)]
(println "here's the argument"))))
Because then you could very elegantly do:
(defn -main [& args]
(apply do_stuff args))

Clojure function/macro to apply functions until one returns something other than nil

Currently I have some code like this:
(defn compute-issue [some args] (or (age-issue some args) (name-issue some args)))
More issue types are coming.
Is there something like this:
(defn compute-issue [some args] (first-not-nil [age-issue name-issue] some args))
; Where first-not-nil would be something like
(defn first-not-nil [fs & args]
(if (empty? fs)
nil
(let [result (apply (first fs) args)]
(if (nil? result)
(recur (rest fs) args)
result))))
I'm new to Clojure. Am I reinventing an existing function?
There is a similar function some-fn in clojure.core:
Takes a set of predicates and returns a function f that returns the first logical true value
returned by one of its composing predicates against any of its arguments, else it returns
logical false. Note that f is short-circuiting in that it will stop execution on the first
argument that triggers a logical true result against the original predicates.
The key differences are some-fn returns another function for the actual function application, and that function will also discard false results, which it sounds like you may not want. This is another simple way to phrase it:
(defn first-not-nil [fs & args]
(first
(for [f fs
:let [r (apply f args)]
:when (some? r)]
r)))

why this partial not working

Here is my code:
(def partial-join (partial (clojure.string/join ",")))
=>(clojure.string/join "," ["foo" "bar"])
"foo,bar"
=> (partial-join ["foo" "bar"])
And it raises this exception:
ClassCastException java.lang.String cannot be cast to clojure.lang.IFn .repl/eval12557 (form-init2162333644921704923.clj:1)
See the doc of clojure.string/join.
clojure.string/join
([coll] [separator coll])
Returns a string of all elements in coll, as returned by (seq coll),
separated by an optional separator.
when only one argument is provided for clojure.string/join, this function regard its argument as collection, so:
user=> (clojure.string/join ",")
","
Next, see the doc of partial.
clojure.core/partial
([f] [f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more])
Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args.
When only one argument provided, partial returns its argument.
user=> (partial (clojure.string/join ","))
","
Try this:
user=> (def partial-join (partial clojure.string/join ","))
#'user/partial-join
user=> (partial-join ["a" "b"])
"a,b"
The problem is NOT with the number of parameters passed to clojure.string/join. The problem is the brackets surrounding clojure.string/join call the function and the result of the function call is passed to partial. What you want to do is pass the function and the first param to partial as below:
(def partial-join (partial clojure.string/join ","))
(partial-join ["foo" "bar"])
;; => "foo,bar"

Why such implementation of partial in clojure.core

I stumbled across implementation of partial function in cojure.core. It looks like this:
(defn partial
"Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args."
{:added "1.0"
:static true}
([f] f)
([f arg1]
(fn [& args] (apply f arg1 args)))
([f arg1 arg2]
(fn [& args] (apply f arg1 arg2 args)))
([f arg1 arg2 arg3]
(fn [& args] (apply f arg1 arg2 arg3 args)))
([f arg1 arg2 arg3 & more]
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
Why it has several parity options if it could have one? Is it just performance optimisation so concat doesn't get called in most cases?
I mean it could look like this otherwise, right?
(defn partial
([f] f)
([f & more]
(fn [& args] (apply f (concat more args))))
)
I also noticed several other functions follow the same pattern.
Yes, it's a performance optimization.
I'ts not just about not calling concat - it's about the fact that & in the argument list requires a collection to be created as well. The clojure core libraries tend to take performance seriously, under the assumption that the basic building blocks of the language will be present in everyone's performance bottleneck.

Implementation of comp

I'm trying to understand how this function work, which is an implementation of comp (from the chapter "Functional Programming" in the book Clojure for the Brave and True):
(defn two-comp
[f g]
(fn [& args]
(f (apply g args))))
The idea is that it takes two functions and apply them to args. What I don't understand is how the args reach the anonymous function, since they are not entered as arguments to two-comp? How can be two-comp used this way?
two-comp returns an anonymous function, which in turn takes args. Look at the body of two-comp:
(fn [& args]
(f (apply g args)))
fn creates a function, and that function definition follows. The return value of fn is what is returned from two-comp.