I'm currently learning Clojure and was looking at the implementation of partial. It implements a lot of cases concretely (and other functions do too) but apply also works with empty lists, so why is the implementation of partial so large? Why is it not:
(defn partial [f & args]
(fn [& inner_args]
(apply f (concat args inner_args))))
This was done for performance:
Ticket
This patch improves performance of partial by only using apply when needed. The code structure follows that of juxt.
Patch
AFAIK these are for performance reasons, for the most common use cases, 0-,1-,2-,3- artity it's a function call, else it does a (bit) more costly apply.
source for completeness (clj 1.10.1):
user=> (source partial)
(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
([] (f arg1))
([x] (f arg1 x))
([x y] (f arg1 x y))
([x y z] (f arg1 x y z))
([x y z & args] (apply f arg1 x y z args))))
([f arg1 arg2]
(fn
([] (f arg1 arg2))
([x] (f arg1 arg2 x))
([x y] (f arg1 arg2 x y))
([x y z] (f arg1 arg2 x y z))
([x y z & args] (apply f arg1 arg2 x y z args))))
([f arg1 arg2 arg3]
(fn
([] (f arg1 arg2 arg3))
([x] (f arg1 arg2 arg3 x))
([x y] (f arg1 arg2 arg3 x y))
([x y z] (f arg1 arg2 arg3 x y z))
([x y z & args] (apply f arg1 arg2 arg3 x y z args))))
([f arg1 arg2 arg3 & more]
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
Related
Suppose I want to apply the parameter p1 and p2 to a list of function calls:
(defn some-func []
(let [p1 a p2 b]
(f1 p1 p2)
(f2 p1 p2)
(f3 p1 p2)
...
))
What's a good and concise way of doing this?
Assuming you want just side-effects, I'd use doseq to force the calls;
iterate the functions you want to call. e.g.
user=> (doseq [f [println println println]] (f 1))
1
1
1
nil
You may want to review the Clojure CheatSheet. The function juxt can do what you want.
Beware, though, juxt is somewhat obscure and can make it hard to read your code.
You can use for or map, both of which return a clojure.lang.LazySeq. Small working example:
(defn f1 [x y] (+ x y))
(defn f2 [x y] (- x y))
(defn f3 [x y] (* x 1))
;; Method 1 - for
(for [f [f1 f2 f3]]
(f 10 5))
;; => (15 5 50)
;; Method 2 - map
(map #(% 10 5) [f1 f2 f3])
;; => (15 5 50)
I'm having problems eval-ing a LazySeq returned by Deriva:
(use 'clojure.core.matrix)
(use 'com.lambder.deriva.core)
(def f1 '(cos (* x y)))
(def f2 '(sin (* x y)))
(def f [f1 f2])
(def u ['x 'y])
(def x 4)
(def y 3)
(defn jacobian [f u]
(map #(partial-derivative f %) u)
)
Returns a LazySeq
((vector (* (* -1 (sin (* x y))) y) (* (cos (* x y)) y)) (vector (* (* -1 (sin (* x y))) x) (* (cos (* x y)) x)))
Which can be successfully eval-ed using the REPL:
(eval (into [] (jacobian f u)))
Results in the correct matrix
[[1.609718754001305 2.5315618761974763] [2.1462916720017398 3.3754158349299686]]
If I put the eval inside the clj file and lein run
(defn -main
[]
(eval (into [] (jacobian f u)))
)
I get Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: sin in this context, compiling:(/tmp/form-init2786363415298022761.clj:1:113) since eval works in a different namespace.
Is there any way to include the clojure.math functions in the temporary namespace generated by eval? Or is there a better way to evaluate the expression?
Maybe you need to use java.lang.Math/sin function of java.
Consider using syntax-quote (`) instead quote (') to obtain fully qualified symbols that you can later eval:
's
=> s
`s
=> user/s
See more about quoting here:
https://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html
I'm not sure this is the best place to post, but why doesn't 2) work? Doesn't the threading macro pass the result of seq into (map str)?
;; 1
(map str (seq (str (* 8 8)))) -> ("6" "4")
;; 2
(defn a [x y]
(-> (* x y)
str
seq
(map str)))
(a 8 8) -> Don't know how to create ISeq from: clojure.core$str
You're using the thread-first macro, which inserts each form as the second item of the next, like this:
(-> (* x y) str seq (map str))
(-> (str (* x y)) seq (map str))
(-> (seq (str (* x y))) (map str))
(map (seq (str (* x y))) str)
What you want is the thread-last macro:
(defn a [x y]
(->> (* x y) str seq (map str)))
(a 8 8) ;=> ("6" "4")
as Elogent points out the macro is putting the arguments in the wrong place. In general when working with macros (and especially writing them) it helps to know about macroexpand-1 and combine it with clojure.pprint/pprint to get a clear view of what is actually running:
user> (clojure.pprint/pprint
(macroexpand-1
'(-> (* x y)
str
seq
(map str))))
(map (seq (str (* x y))) str)
nil
Which we can see doesn't quite look right. So next we fiddle with it until it expands to what we expect:
user> (clojure.pprint/pprint
(macroexpand-1
'(->> (* x y)
str
seq
(map str))))
(map str (seq (str (* x y))))
nil
There are a variety of threading macros to help with situations like this, especially as-> which lets you give an explicit name to the threaded value when you need to thread functions that alternate using the first and last argument for the important input:
user> (as-> (* 7 42) x
(str x)
(seq x)
(map str x))
("2" "9" "4")
Here is an alternative that is good to know (it's read from right to left):
(defn a [x y]
((comp (partial map str) seq str *)
x y))
This might be useful in contexts where you want to separate the transformations to apply, from the data they're applied to (I would welcome criticism on the subject 😃).
You might also consider using the it-> threading form from the Tupelo library, which is designed to avoid thread-first vs thread-last worries. Consider this code:
(ns clj.core
(:use tupelo.core))
(defn a [x y]
(it-> (* x y)
(str it)
(seq it)
(map str it)))
(spyx (a 8 8))
(defn -main [] )
Which produces:
(a 8 8) => ("6" "4")
The it-> macro uses the placeholder it to explicitly choose where to place the result of each successive form. This is an easy way to simplify code and avoid this type of error.
The core.clj code for Clojure itself (available at https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj) gives the following definition for comp:
(defn comp
"Takes a set of functions and returns a fn that is the composition
of those fns. The returned fn takes a variable number of args,
applies the rightmost of fns to the args, the next
fn (right-to-left) to the result, etc."
{:added "1.0"
:static true}
([] identity)
([f] f)
([f g]
(fn
([] (f (g)))
([x] (f (g x)))
([x y] (f (g x y)))
([x y z] (f (g x y z)))
([x y z & args] (f (apply g x y z args)))))
([f g & fs]
(reduce1 comp (list* f g fs))))
I'm new to Clojure and trying to understand both the technical side and idiomatic style sides of it and I'm wondering what the reason is for including so many cases when two functions are passed into comp. Why bother with the [x y] and [x y z] cases at all?
As Mars said, this is done for efficiency. Dispatching directly is faster than using apply. Unrolling functions like this is quite common to speed up the performance, juxt is unrolled in a similar fashion.
In writing a function which takes multiple sets as inputs, I would like to be able to output their set union. So far I have written down the function:
(defn foo [x y]
(clojure.set/union x y))
But have also tried something along the lines of
(defn foo
([x y] (clojure.set/union x y))
([x y & args] (clojure.set/union x y args)))
which outputs funky results that do not match
(clojure.set/union #{1 2 3} #{2 3 4} #{4 5 6})
Clearly I am missing some simple implementation of the set functions, while trying to build foo, a multiple arity function.
Your problem is that args is a Seq containing all the sets you passed after the first two, but the union function expects its arguments to be sets.
What you want is to apply the function:
(defn foo
([x y] (clojure.set/union x y))
([x y & args] (apply clojure.set/union x y args)))