Sequentially calling a function with elements from a vector - clojure

Suppose I have a function f that accepts two arguments x & y. I also have a vector X composed of elements x1, x2, ... xn.
How can I write a function g, where g(X, y) calls f(xi, y) for all x?
Further specification: I would like g to return a vector, where each element stores the result of f(xi, y). My understanding is that I should be considering map or mapv.

You can use map to implement it.
I'm using a lambda expression here to define a function which takes only one argument.
(defn f [x y ] (...) )
// apply f x y to every element of xs
// in order to do this we need a function which takes only one argument the x_i and takes the second argument from somehere else - the second argument of g
// that's what the lambda \x -> f x y does - in short form.
(defn g [xs y] (map (fn [x] (f x y)) xs))
for example
(def X [1 2 3 4])
(defn f [x y] (* x y))
(g X 3)
;=> (3 6 9 12)

If you can rearrange the definition of f so that y is the first parameter, you can do it this way:
(defn f [y x] ...)
(map (partial f y) xs)
partial returns a function in which y is "baked in" as the first argument to f. For functions that take more than two arguments, you can pass additional arguments to partial, and the returned function will accept arguments for whatever parameters are still unfilled.

Here is a simple way using for:
(def y 5)
(def xx (range 5)) ;=> [0 1 2 3 4]
(defn ff [x y] (+ y (* x x)))
(defn gg [xx y] (for [x xx] (ff x y)))
(gg xx y)
;=> (5 6 9 14 21)
You could also use repeat:
(defn g2 [xx y] (mapv ff xx (repeat y)))
(g2 xx y)
;=> [5 6 9 14 21]

Related

How to apply the same arguments to a list of function calls in clojure?

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)

Evaluate Vector of Forms with Parameters

I've been working to figure out a was to evaluate collections of forms with arguments.
An example function:
(defn x
[a b c]
(+ a b c))
I would like to evaluate collections of the function x, where only some parameters are defined and others are passed in to end up with a list of the products of the evaluations of the x functions in the collection:
(defn y
[z]
(map #(eval %) [(x z 1 1) (x z 2 2) (x z 8 64)]))
The question is: how do I introduce z as a parameter to each of the functions in the collection when I map eval to each? Is this possible?
I am trying to avoid typing them all out because I have many inputs (hundreds) that I want to pass to x where I only have a small set of the second and third parameters (five or so) that I care about.
Is there a better way to accomplish this?
Thanks!
First, let's use some more explanatory names, simplify the definition of x, and not use eval:
(defn sum [& xs]
(apply + xs)) ;; could be inlined instead of a function
(defn sum-with [z]
(map (partial apply sum)
[[z 1 1]
[z 2 2]
[z 8 64]]))
(sum-with 3)
=> (5 7 75)
But I assume your real world problem is something more complex than summing numbers, so I'll assume your x function is doing something else and requires some positional arguments i.e. the order of arguments matters:
(defn transmogrify [this n1 n2 that]
(+ n1 n2 (* this that)))
(defn evaluate-sums [a b]
(map (partial apply transmogrify)
[[a 1 1 b]
[a 2 2 b]
[a 8 64 b]]))
(evaluate-sums 3 9)
=> (29 31 99)
So if I understand correctly, you can accomplish your goal just by applying sequences of arguments to your function. Or to be more explicit with args/not use apply, just use a more specific anonymous function with map:
(defn evaluate-sums [z]
(map (fn [[this n1 n2 that]]
(transmogrify this n1 n2 that))
[[z 1 1 99]
[z 2 2 360]
[z 8 64 -1]]))
I am trying to avoid typing them all out because I have many inputs (hundreds) that I want to pass to x where I only have a small set of the second and third parameters (five or so) that I care about.
If your "fixed" arguments are always the same arity, then you can use variadic arity for the rest of the arguments:
(defn sum [a b & cs]
(apply + a b cs))
(defn evaluate-sums [zs]
(map (fn [[a b & cs]]
(apply sum a b cs))
[[1 1 zs]
[2 2 zs]
[8 64 zs]]))
Where zs is a collection/sequence of your extra arguments.

Not understanding reduce with anonymous function

I am reading Living Clojure, and this example of reduce is throwing me off.
(reduce (fn [r x]
(+ r (* x x)))
[1 2 3])
[1 2 3] is the input to reduce, along with the anonymous function.
If each member of the vector is passed in, that would only fill in r or x parameters, where does the other parameter come from?
Is there a way to step through to watch the parameters and output change?
There's a description of the first argument on ClojureDocs, but I have to admit it's not really descriptive.
The function you pass as the first argument takes two parameters, the first one is total, the second one is current. If you call reduce with only two arguments, total in first iteration is the first item of the collection, while current in first iteration is the second item of the collection. If you pass three parameters, the second one is initial value that is passed as total in the first iteration, while the first item of the collection is passed as current in first iteration:
(reduce (fn [r x] (+ r x)) 0 [1 2 3])
would iterate like this:
(+ 0 1) ;; initial value and first item of the collection
(+ (+ 0 1) 2) ;; result and second item of the collection
(+ (+ (+ 0 1) 2) 3) ;; result and third item of the collection
while without initial value
(reduce (fn [r x] (+ r x)) [1 2 3])
would iterate like this:
(+ 1 2) ;; no initial value -> first and second item of the collection
(+ (+ 1 2) 3) ;; result and third item of the collection
You could as well just add a println to see each iteration's inputs:
(reduce
(fn [r x]
(do
(println (str "r = " r ", x = " x ", (* x x) = " (* x x) ", (+ r (* x x)) = " (+ r (* x x))))
(+ r (* x x))))
[1 2 3])
the result of running it in REPL is
r = 1, x = 2, (* x x) = 4, (+ r (* x x)) = 5
r = 5, x = 3, (* x x) = 9, (+ r (* x x)) = 14
14

Set union with multiple arity

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)))

Can clojure evaluate a chain of mixed arity functions and return a partial function if needed?

Suppose you have three functions of arity 1, 2 and 3 as below:
(defn I [x] x)
(defn K [x y] x)
(defn S [x y z] (x z (y z)))
Does clojure have an evaluation function or idiom for evaluating:
(I K S I I) as (I (K (S (I (I)))))
returning a parital function of arity 2?
I am considering creating a macro that can take the simple function definitions above and expand them to multi-arity functions that can return partial results. I would not want to create the macro if there is already a built in or idiomatic way to accomplish this.
Here is what the expanded macros would like for the above functions:
(defn I
([x] I x)
([x & more] (apply (I x) more)))
(defn K
([x] (partial K x))
([x y] x)
([x y & more] (apply (K x y) more)))
(defn S
([x] (partial S x))
([x y] (partial S x y))
([x y z] (x z (y z)))
([x y z & more] (apply (S x y z) more)))
I'm not sure I fully understand what you are trying to do, but the comp function is useful for doing this kind of "function chaining" you seem to be talking about. For example:
user> ((comp vec rest list) 1 2 3 4 5)
=> [2 3 4 5]
Which is equivalent to:
user> (vec (rest (list 1 2 3 4 5)))
=> [2 3 4 5]
In your case, if you have the list (I K S I I), and you want to evaluate it as (I (K (S (I (I))))), I would use (reduce comp ...), but you could also use (apply comp ...).
user> ((reduce comp [vec rest list]) 1 2 3 4 5)
=> [2 3 4 5]
user> ((apply comp [vec rest list]) 1 2 3 4 5)
=> [2 3 4 5]
You may also be interested in the -> or ->> macros. These macros nest their arguments sequentially into the next arguments. The -> macro will nest into the first position of the next expression, whereas the ->> macro will nest into the last position of the next expression. If the "next thing" is a function, both will behave the same, and form an expression of (function nested-things-so-far), and continue along.
Really, examples are best:
(-> 1 (+ 10) (- 100) inc)
;//Expands to...
(inc (- (+ 1 10) 100))
;//Evaluating in the REPL...
user> (-> 1 (+ 10) (- 100) inc)
=> -88
(->> 1 (+ 10) (- 100) inc)
;//Expands to...
(inc (- 100 (+ 10 1)))
;//Evaluating in the REPL...
user> (-> 1 (+ 10) (- 100) inc)
=> 90
However, it seems more like you want to do something involving auto-currying (although, again, I don't think I fully understand), and for that I don't know of anything pre-existing built-in way.