I have a function that takes three arguments say somefunction [param1 param2 param3] and a vector with values say [val1 val2 val3 val4 ...]
I would like to repeatedly call the somefunction with the first argument param1 as fixed and the other two parameters passed in the combination val1 val2, val2 val3, val3 val4 ... etc. which is equivalent to (somefunction sampleparam1 val1 val2) (somefunction sampleparam1 val2 val3) (somefunction sampleparam1 val3 val4)... etc. IS there a way to elegantly do this in clojure?
I'm not sure what you want to do with the results of each call to somefunction so I'll assume it is executed for its side-effects and use doseq.
(let [f (partial somefunction param1)]
(doseq [args (partition 2 1 [val1 val2 val3 val4])]
(apply f args)))
clojure.core/partition:
(partition 2 1 [1 2 3 4]) ;; ((1 2) (2 3) (3 4))
clojure.core/partial
(def plus10 (partial + 10))
(plus10 5) ;; 15
clojure.core/apply
(apply + [1 2 3]) ;; 6
Note: you can get away without using partial since apply accepts intervening arguments: (apply somefunction param1 args)
Vinoth, there is:
You are first asking to create a function that takes a maximum of three (3) arguments: [param1 param2 param3] but you want to be able to fix the first parameter. In addition, while you have stated that you have a vector of arguments it appears, from your write up, that you want to go through the vector of values such that the first call to somefunction takes the 1st and 2nd item from the vector, the second call takes the 2nd and 3rd item from the vector, and so on until the vector is exhausted.
The first part of your question (fixed first parameter) can be solved with:
(partial somefunction sampleparam1)
The second part is a bit more complicated and without more details I can only guess. But here is a small demonstration of one approach:
(defn somefunction
[param1 param2 param3]
(+ param1 param2 param3))
(def part (partial somefunction 100))
(let [x [1 2 3 4 5]
y (first x)
z (second x)]
(part y z))
If you could explain more about
Are the value vectors consistent in length?
What does somefunction do?
My first thought went to using reduce or loop but I hesitate to assume too much.
I think I get the gist of your question.
;; a function that returns the vector as pairs of sub-vectors
(defn pairs [v]
(map vector v (rest v)))
This splits your vector [val1 val2 val3...] into a sequence of pairs as you wanted.
Example output from this is
(pairs [1 2 3])
=> ([1 2] [2 3])
As #Kyle has pointed out you can also use (partition 2 1 v) here too, as you're only really interesting in sequences, not actual vectors as they get squashed later into parameters via apply.
Next, your function needs to do something. For illustration in the output, I'll just return a map with params as values to the keys :a :b :c
(defn somefn [p1 p2 p3]
{:a p1 :b p2 :c p3})
now create a new function that calls your function, but with a constant first arg. I'll just use :p1 as a marker. Thus you only have to call (partial-somefn p2 p3) which will call (somefn :p1 p2 p3)
(def partial-somefn (partial somefn :p1))
then to call it with pairs from your vector (or sequence)...
either use map...
(map #(apply partial-somefn %) (pairs [1 2 3]))
=> ({:b 1, :c 2, :a :p1} {:b 2, :c 3, :a :p1})
or use doseq for side effects...
(doseq [ps (pairs [1 2 3])]
(apply partial-somefn ps))
or a for loop
(for [ps (pairs [1 2 3])]
(apply partial-somefn ps))
=> ({:b 1, :c 2, :a :p1} {:b 2, :c 3, :a :p1})
You can see that the maps returned show the parameters were called in sequence with the constant first parameter.
So the condensed version is
(defn somefn [p1 p2 p3]
;; your code here
)
(def v [:v1 :v2 :v3])
(let [pairs (fn [v] (map vector v (rest v)))
pf (partial somefn :param1)]
(map #(apply pf %) (pairs v)))
or use one of the for or doseq variations depending on what somefn does
Related
Is there a way to use a single list comp to achieve the following or do I need some other method?
(def args '([[:db/foo 1 2] [:db/bar 3 4]] {:a 1 :b 2}))
(defn myfunc []
"Want to run inner loop only once if arg is a map."
(for [arg args [cmd & params] arg] ; 'cmd & params' are meaningless if map.
(if (map? arg)
arg
(into [cmd] params))))
Above code produces
=> [[:db/foo 1 2] [:db/bar 3 4] {:a 1, :b 2} {:a 1, :b 2}]
But I actually want
=> [[:db/foo 1 2] [:db/bar 3 4] {:a 1, :b 2}]
Obviously this isn't the full function, I'm doing transforms if the arg is in vector form but want to let map form pass straight through (without being duplicated).
Update: I've found that a list comprehension has its roots in set builder notation, whereas 'conditionally executing the inner loop' is actually an imperative notion, so it's not surprising this isn't easy to express with a single list comprehension, which is a totally fp construct.
Is this what you want to do?:
Build a new sequence from an existing sequence. For every element in the input sequence, there are two possible cases:
It is a map: In that case, just append it to the result sequence
Otherwise it is a sequence and its elements should possibly be transformed and appended to the result sequence
If this is what you want to do, this computation can conveniently be expressed by first mapping the elements of the input sequence to subsequences and then concatenating those sequences to form the resulting sequence.
As suggested by #cfrick, there is mapcat that combines mapping with concatenation, either by passing in a sequence directly to mapcat
(mapcat (fn [x] (if (map? x) [x] x)) args)
or by using mapcat as a transducer
(into [] (mapcat (fn [x] (if (map? x) [x] x))) args)
I don't think for is suitable for expressing this computation.
before I propose a solution, I have a few remarks on the function myfunc that you provided:
the doc string is misplaced. I know it's weird but the doc string must be before the arguments of a function, so before [],
your usage of for instruction is not what you expect I think. You should take a look on the example in the documentation here. Mainly the for instruction is nice to construct Cartesian product from list.
I hope that I understood correctly what you want to achieve. In my proposition, I use a recursion through loop instruction to build a vector which will contain every arguments:
(defn myfunc "Want to run inner loop only once if arg is a map."
[& args]
(loop [arg-to-parse args
res []]
(if (empty? arg-to-parse)
res
(let [arg (first arg-to-parse)
new-arg-to-parse (rest arg-to-parse)]
(if (map? arg)
(recur new-arg-to-parse (conj res arg))
(recur new-arg-to-parse (into res arg))
)))))
(myfunc [[:db/foo 1 2] [:db/bar 3 4]] {:a 1 :b 2})
;; => [[:db/foo 1 2] [:db/bar 3 4] {:a 1, :b 2}]
(myfunc {:a 1 :b 2} [[:db/foo 1 2] [:db/bar 3 4]])
;; => [{:a 1, :b 2} [:db/foo 1 2] [:db/bar 3 4]]
In Clojure, I have a map like this:
(def data {:a 1 :b 2 :c 3})
I want to sum all the elements and get 6 as a result. I know I should probably use reduce, but I'm at a loss at how to do it correctly.
There are two easy ways you can do this.
With reduce
(reduce + (vals data))
Or with apply
(apply + (vals data))
They are equivalent for associative functions.
I'd suggest that apply is more idiomatic, because + is already implemented via reduce.
That is, if we calculate (+ 1 2 3), the result is 6. So it's natural to ask why (+ (vals data)) isn't sufficient.
The result of (vals data) is the list (1 2 3). + sees this as a single argument and just returns that value... oops.
(+ (vals data))
=> (1 2 3)
apply works by essentially unpacking the list.
You are correct, you should reduce here. vals will get you the values you want to add up, then just reduce them over the addition function.
user=> (def data {:a 1 :b 2 :c 3})
#'user/data
user=> (vals data)
(3 2 1)
user=> (reduce + (vals data))
6
I want to write a function that concatenates vectors or matrices, which can take arbitrary inputs. To combine two vectors I've written the follow code. It also also matrices to be combined such that columns are lengthened.
(defn concats
([x y] (vec (concat x y))))
Where I am stuck is extending the input to n vectors or matrices, and combining matrices to make longer rows.
Ex) (somefunction [[:a :b] [:c :d]] [[1 2] [3 4]] 2]
[[:a :b 1 2] [:c :d 3 4]]
The 2 in the input designates level to concatenate.
If you're not interested in "how it works", here's the solution right up front (note that level is zero-indexed, so what you've called the 1st level I'm calling the 0th level):
(defn into* [to & froms]
(reduce into to froms))
(defn deep-into*
[level & matrices]
(-> (partial partial mapv)
(iterate into*)
(nth level)
(apply matrices)))
The short answer for how it works is this: it iteratively builds up a function that will nest the call to into* at the correct level, and then applies it to the supplied matrices.
Regular old into, given a vector first argument, will concatenate the elements of the second argument onto the end of the vector. The into* function here is just the way I'm doing vector concatting on a variable number of vectors. It uses reduce to iteratively call into on some accumulated vector (which starts as to) and the successive vectors in the list froms. For example:
user> (into* [1 2] [3 4] [5 6])
> [1 2 3 4 5 6]
Now for deep-into*, I had to recognize a pattern. I started by hand-writing different expressions that would satisfy different "levels" of concatenation. For level 0, it's easy (I've extrapolated your example somewhat so that I can make it to level 2):
user> (into* [[[:a :b] [:c :d]]] [[[1 2] [3 4]]])
> [[[:a :b] [:c :d]] [[1 2] [3 4]]]
As for level 1, it's still pretty straightforward. I use mapv, which works just like map except that it returns a vector instead of a lazy sequence:
user> (mapv into* [[[:a :b] [:c :d]]] [[[1 2] [3 4]]])
> [[[:a :b] [:c :d] [1 2] [3 4]]]
Level 2 is a little more involved. This is where I start using partial. The partial function takes a function and a variable number of argument arguments (not a typo), and returns a new function that "assumes" the given arguments. If it helps, (partial f x) is the same as (fn [& args] (apply f x args)). It should be clearer from this example:
user> ((partial + 2) 5)
> 7
user> (map (partial + 2) [5 6 7]) ;why was six afraid of seven?
> (7 8 9)
So knowing that, and also knowing that I'll want to go one level deeper, it makes some sense that level 2 looks like this:
user> (mapv (partial mapv into*) [[[:a :b][:c :d]]] [[[1 2][3 4]]])
> [[[:a :b 1 2] [:c :d 3 4]]]
Here, it's mapping a function that's mapping into* down some collection. Which is kind of like saying: map the level 1 idea of (mapv into* ...) down the matrices. In order to generalize this to a function, you'd have to recognize the pattern here. I'm going to put them all next to each other:
(into* ...) ;level 0
(mapv into* ...) ;level 1
(mapv (partial mapv into*) ...) ;level 2
From here, I remembered that (partial f) is the same as f (think about it: you have a function and you're giving it no additional "assumed" arguments). And by extending that a little, (map f ...) is the same as ((partial map f) ...) So I'll re-write the above, slightly:
(into* ...) ;level 0
((partial mapv into*) ...) ;level 1
((partial mapv (partial mapv into*)) ...) ;level 2
Now an iterative pattern is becoming clearer. We're calling some function on ... (which is just our given matrices), and that function is an iterative build-up of calling (partial mapv ...) on into*, iterating for the number of levels. The (partial mapv ...) part can be functionalized as (partial partial mapv). This is a partial function that returns a partial function of mapving some supplied arguments. This outer partial isn't quite necessary because we know that the ... here will always be one thing. So we could just as easily write it as #(partial mapv %), but I so rarely get a chance to use (partial partial ...) and I think it looks pretty. As for the iteration, I use the pattern (nth (iterate f initial) n). Perhaps another example would make this pattern clear:
user> (nth (iterate inc 6) 5)
> 11
Without the (nth ...) part, it would loop forever, creating an infinite list of incrementing integers greater than or equal to 5. So now, the whole thing abstracted and calculated for level 2:
user> ((nth (iterate (partial partial mapv) into*) 2)
[[[:a :b][:c :d]]] [[[1 2][3 4]]])
> [[[:a :b 1 2] [:c :d 3 4]]]
Then, using the -> macro I can factor out some of these nested parantheses. This macro takes a list of expressions and recursively nests each into the second position of the successive one. It doesn't add any functionality, but can certainly make things more readable:
user> ((-> (partial partial mapv)
(iterate into*)
(nth 2))
[[[:a :b][:c :d]]] [[[1 2][3 4]]])
> [[[:a :b 1 2] [:c :d 3 4]]]
From here, generalizing to a function is pretty trivial--replace the 2 and the matrices with arguments. But because this takes a variable number of matrices, we will have to apply the iteratively-built function. The apply macro takes a function or macro, a variable number of arguments, and finally a collection. Essentially, it prepends the function or macro and the supplied arguments onto the final list, then evaluates the whole thing. For example:
user> (apply + [1 5 10]) ;same as (+ 1 5 10)
> 16
Happily, we can stick the needed apply at the end of the (-> ...). Here's my solution again, for the sake of symmetry:
(defn deep-into*
[level & matrices]
(-> (partial partial mapv)
(iterate into*)
(nth level)
(apply matrices)))
Using the concats function you listed in the question:
user=> (map concats [[:a :b] [:c :d]] [[1 2] [3 4]])
([:a :b 1 2] [:c :d 3 4])
this doesn't take into account the level as you listed, but it handles the input given
Taking arbitrary number of arguments needs a replacement concats function
(defn conc [a b & args]
(if (nil? (first args))
(concat a b)
(recur (concat a b) (first args) (rest args))))
Here are two examples
user=> (map conc [[:a :b] [:c :d]] [[1 2] [3 4]] [["w" "x"] ["y" "z"]])
((:a :b 1 2 "w" "x") (:c :d 3 4 "y" "z"))
user=> (map conc [[:a :b] [:c :d] [:e :f]] [[1 2] [3 4] [5 6]] [["u" "v"] ["w" "x"] ["y" "z"]])
((:a :b 1 2 "u" "v") (:c :d 3 4 "w" "x") (:e :f 5 6 "y" "z"))
Here are two different solutions for a function which will return a vector that's the concatenation of an arbitrary number of input collections:
(defn concats [& colls]
(reduce (fn [result coll]
(into result coll))
[]
colls))
(defn concats [& colls]
(vec (apply concat colls)))
The [& arg-name] notation in the argument lists is how you specify that the function is "variadic" - meaning it can accept a variable number of arguments. The result is that colls (or whatever name you pick) will be a sequence of all the arguments in excess of the positional arguments.
Functions can have multiple arities in Clojure, so you can also do things like this:
(defn concats
([x]
(vec x))
([x y]
(vec (concat x y)))
([x y & colls]
(vec (apply concat (list* x y colls)))))
However, only one of the overloads can be variadic, and its variadic part must come last (i.e. you can't do [& more n], only [n & more].
The Clojure.org page on special forms has more useful information on argument lists in Clojure (in the section on fn).
The function below correctly handles the example input/output you provided. Unfortunately I don't think I understand how you want the levels (and associated numeric input) to work well enough to generalize it as far as you're looking for.
(defn concats [x y]
;; only works with two inputs
(vec (map-indexed (fn [i v] (into v (nth y i)))
x)))
(concats [[:a :b] [:c :d]] [[1 2] [3 4]]) ;=> [[:a :b 1 2] [:c :d 3 4]]
But maybe it will give you some ideas anyway, or if you can add more information (especially examples of how different levels should work) I'll see if I can be more help.
I want something that gives me the sequence of actual values passed to a function, similar to the arguments value in a javascript function.
I am aware that I can grab the entire function argument list using
(defn fx [& args]
args)
<= (fx {:a 1} 2)
=> ({:a 1} 2)
But this removes the arity on my function. I want to have something like
(defn fx [{:keys [a]} b]
(MAGIC_FUNCTION_THAT_RETURNS_THE_ARGS_VALUES))
<= (fx {:a 1} 2)
=> ({:a 1} 2)
Is it possible to get a raw sequence of the values passed to a function?
By the time the function body is executed, the parameters have already been destructured. You could define your own defn macro and expose those values. I know Lighttable does this in their Instarepl to show the argument values.
Using argument destruction can help. The following works fine for me (as far as I know, it also works for old versions of clojure).
(defn example [ & [a b :as args]] [a b args])
(example 1 2)
=> [1 2 (1 2)]
The key point is that you can destruct the argument after &. The drawback is that it is possible to call the function with more arguments than expected (for example (example 1 2 3) is a valid invocation. Special care should be taken if this might be a problem.
Note: I came across this question while I was searching for similar feature. I kept digging and using an idea from here and :as as it was suggested in this answer, I found a solution for my problem.
I don't know of a way to do this as you describe, but depending on what you're wanting to do there are some options.
If you're wanting to ensure the function is only called with two arguments, consider a precondition:
(defn fx [& args]
{:pre [(= 2 (count args))]}
args)
user=> (fx 1 2)
(1 2)
user=> (fx 1 2 3)
AssertionError Assert failed: (= 2 (count args)) user/fx (NO_SOURCE_FILE:1)
If you're wanting to keep track of your intended arity of a function, but still have access to a vector of all args, you could add your own metadata:
(defn
^{:my.ns/arglists '([{:keys [a]} b])}
fx [& args]
args)
user=> (fx 1 2)
(1 2)
user=> (-> #'fx meta :my.ns/arglists first)
[{:keys [a]} b]
If you're just wanting access to the destructured values you described and access to an args value, you could use let:
(defn fx [{:keys [a]} b]
(let [args [{:a a} b]]
[a b args]))
user=> (fx {:a 1 :c 3} 2)
[1 2 [{:a 1} 2]]
user=> (fx {:a 1 :c 3} 2 4)
ArityException Wrong number of args (3) passed to: user$fx clojure.lang.AFn.throwArity (AFn.java:437)
You could also do a combination of these.
Not very nice as it requires to pass params as a vector, but seems apt
user.main=> (defn fx [[{:keys [a] :as e} b :as o]] [a b e o])
#'user.main/fx
user.main=> (fx [{:a 1} 2])
[1 2 {:a 1} [{:a 1} 2]]
user.main=>
You can use a macro to bind the arguments to symbol, _args in this example.
(defmacro defn-args [name args & body]
`(defn ~name ~args
(let [~'_args ~args]
~#body)))
You can then use _args in the body of the function to refer to the arguments:
user> (defn-args foo [{:keys [a b]} y z] _args)
user> (foo {:a 1 :b 10} 2 3)
[{:a 1, :b 10} 2 3]
This is the best I could cook up.
(def ^:dynamic *arguments* nil)
(defn unstructure [form]
(cond
(or (vector? form) (map? form)) (gensym)
(= form '&) '&
:else form))
(defmacro bind-args-defn [name args & body]
(let [simple-args (vec (map unstructure args))
i (.lastIndexOf simple-args '&)
[h r] (split-at (if (neg? i) (count simple-args) i) simple-args)
r (drop 1 r)]
`(defn ~name
~simple-args
(binding [*arguments* (lazy-cat ~#(map vector h) ~#r)]
(let [~args *arguments*]
~#body)))))
(bind-args-defn ;;my special val binding defn
silly ;;the name
[{:keys [a]} [b & c] & d] ;;the arg vector
{:vals *arguments* :a a :b b :c c :d d}) ;;the body
Obviously, this does not accept the full set of defn options (metadata, docstring, pre and post, arities, etc) that can be passed to defn, but I think it illustrates the idea.
It works by capturing the args vector, and then creating a simple-args vector of the same length as the original args but with no destructuring; using that as the defn argument vector. It then massages this simple-args vector into a sort of flat vector without &, which it assigns to *arguments*. *arguments* is then destructured using the original args vector. Kind of convoluted, but it does what I want at the moment.
> (silly {:a 1} [2 3 4] 5 6)
{:vals ({:a 1} [2 3 4] 5 6), :a 1, :b 2, :c (3 4), :d (5 6)}
I'm hitting some kind of mental roadblock related to destructuring...
(sorted-set 4 2 5)
gives:
#{2 4 5}
But How I can get that same sorted set from:
((fn [???] (sorted-set ???)) [4 2 5])
or from a set (unsorted) passed as an argument:
((fn [???] (sorted-set ???)) #{4 2 5})
I tried several destructuring, I was thinking that:
((fn [#{elems}] (sorted-set elems)) #{4 2 5})
would work but this is not the case.
I'd like to know how to do that and it would be even better if you could explain why my way of reasoning is bogus...
the sorted-set function param is a var-arg: [& keys], which means that if you have a collection and you want to call that function you need to use the apply function like:
user=> (def v [4 8 2])
#'user/v
user=> (apply sorted-set v)
#{2 4 8}
The signature of a function that accepts a collection and returns a sorted-set would be like:
user=> (defn to-ss [c] (apply sorted-set c))
#'user/to-ss
user=> (to-ss v)
#{2 4 8}
You could also create an empty sorted-set and then add all the elements of the collection to it:
(defn to-ss [c] (into (sorted-set) c))
Note that if you were to define your function with a var-arg parameter, you will need to use apply to both call the function and create the sorted-set:
user=> (defn to-ss [& items] (apply sorted-set items))
#'user/to-ss
user=> (apply to-ss v)
#{2 4 8} <-- expected value
user=> (to-ss v)
#{[4 8 2]} <-- sorted-set with just one value