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
Related
Let's imagine we want to compute two different functions on some given input. How can we do that with transducers?
For example, let's say we have these two transducers:
(def xf-dupl (map #(* 2 %)))
(def xf-inc (map inc))
Now, I would like some function f that takes a collection of transducers and returns a new transducer that combines them, as follows:
(into [] (f [xf-dupl xf-inc]) (range 5))
; => [[0 2 4 6 8] [1 2 3 4 5]]
There should probably be a very simple solution to this, but I cannot find it.
Note: I have tried with cgrand/xforms library's transjuxt, but there I get the following
(into [] (x/transjuxt {:a xf-dupl :b xf-inc}) (range 5))
; => [{:a 0 :b 1}]
Thanks for your help!
Using cgrand/xforms you can define f as
(defn f
[xfs]
(comp
(x/multiplex (zipmap (range) xfs))
(x/by-key (x/into []))
(map second)))
Calling f as you outlined in your question yields
user> (into [] (f [xf-dupl xf-inc]) (range 5))
[[0 2 4 6 8] [1 2 3 4 5]]
I have a higher-order map-like function that returns a hashmap representing the application (input to output) of the function.
(defn map-application [f coll] (into {} (map #(vector % (f %)) coll)))
To be used thus:
(map-application str [1 2 3 4 5])
{1 "1", 2 "2", 3 "3", 4 "4", 5 "5"}
(map-application (partial * 10) [1 2 3 4 5])
{1 10, 2 20, 3 30, 4 40, 5 50}
Does this function already exist, or does this pattern have a recognised name?
I know it's only a one-liner, but looking at the constellation of related functions in clojure.core, this looks like the kind of thing that already exists.
I guess the term you are looking for is transducer.
https://clojure.org/reference/transducers
in fact the transducing variant would look almost like yours (the key difference is that coll argument is passed to into function not map), but it does it's job without any intermediate collections:
user> (defn into-map [f coll]
(into {} (map (juxt identity f)) coll))
#'user/into-map
user> (into-map inc [1 2 3])
;;=> {1 2, 2 3, 3 4}
this can also be done with the simple reduction, though it requires a bit more manual work:
user> (defn map-into-2 [f coll]
(reduce #(assoc %1 %2 (f %2)) {} coll))
#'user/map-into-2
user> (map-into-2 inc [1 2 3])
;;=> {1 2, 2 3, 3 4}
What you're describing is easily handled by the built-in zipmap function:
(defn map-application
[f coll]
(zipmap coll (map f coll)))
(map-application (partial * 10) [1 2 3 4 5])
=> {1 10, 2 20, 3 30, 4 40, 5 50}
Usually map-indexed function maps each list item to a respective index where the first index is 0, the second is 1 etc.
Is it possible to have the index start at another number and proceed from there?
Easiest way is to just remember that you can pass multiple sequences to map.
(map vector [:a :b :c] (iterate inc 100))
=> ([:a 100] [:b 101] [:c 102])
You simply wrap the index with another function in the receiving function
For example if we wanted to start at 1 instead of zero we would simply use inc
(map-indexed (fn [i v] (vector (inc i) v)) ["one" "two" "three"])
Will return
([1 "one"] [2 "two"] [3 "three"])
map-indexed does not allow this. However, it's easy to write your own version that lets you do it.
(defn map-indexed-from [n f coll]
(map f (range n Double/POSITIVE_INFINITY) coll))
Example usage:
user> (map-indexed-from 5 vector [:a :b :c])
([5 :a] [6 :b] [7 :c])
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)}