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)))
Related
My question is whether given a hashmap
(def my-map {'x 1 'y 2 'z})
I can apply it to an anonymous function,
(fn [x y z] (+ x (* y z))
so that the arguments match the keys in the map, somthing like
(apply-ish my-map (fn [x y z] (+ x (* y z)))
Is there an easy fix to this problem? I feel like there is but I cant figure it out.
You can use map destructuring:
user> (def my-map {'x 1 'y 2 'z 3})
#'user/my-map
user> ((fn [{x 'x y 'y z 'z}] (+ x (* y z))) my-map)
7
You can simplify a bit with this form of desctructuring:
user> ((fn [{:syms [x y z]}] (+ x (* y z))) my-map)
7
or if you use keywords for your map keys:
user> (def my-map2 {:x 1 :y 2 :z 3})
#'user/my-map2
user> ((fn [{:keys [x y z]}] (+ x (* y z))) my-map2)
7
personally, i would not modify the function to accept the map as the arg, since it makes the function itself way less generic. The alternative (and idiomatic i guess, for any language) solution is to select needed keys from the map before passing them to function. That is quite easy, since both map and symbol (and keyword too) have function semantics in clojure:
user> (apply f (map my-map ['x 'y 'z]))
;;=> 7
user> (apply f ((juxt 'x 'y 'z) my-map))
;;=> 7
There's an example in the book (P252), it's about the &env in macro, I just don't understand how to get the result{x 1, y 2}
(defmacro spy-env []
(let [ks (keys &env)]
`(prn (zipmap '~ks [~#ks]))))
(let [x 1 y 2]
(spy-env)
(+ x y))
; {x 1, y 2}
;= 3
I tried in the REPL like this:
user=> (defmacro spy-env [] (let [ks (keys &env)] `(prn ~#(keys &env))))
#'user/spy-env
user=> (let [x 1 y 2] (spy-env))
2 1
It's wried.
Expanding the macro would be a great way for you to see how it works, but unfortunately macroexpand-1 doesn't convey the right bindings for &env. This example:
(let [x 1 y 2] (spy-env))
Actually expands out to:
(let [x 1 y 2] (prn (zipmap '(x y) [x y])))
Do you get it? Within the first sequence, x and y are not evaluated, but within the second, they are. So it zips the symbols to whatever they evaluate to. Within that let block, (zipmap '(x y) [x y]) evaluates to {x 1 y 2}.
a) If you try the code of the book it does output the right value
user=> (defmacro spy-env []
#_=> (let [ks (keys &env)]
#_=> `(prn (zipmap '~ks [~#ks]))))
#'user/spy-env
user=> (let [x 1 y 2] (spy-env))
{x 1, y 2}
nil
user=> (let [x 1 y 2]
#_=> (spy-env)
#_=> (+ x y))
{x 1, y 2}
3
b) now your code is different
initial code :
`(prn (zipmap '~ks [~#ks]))
vs
`(prn ~#(keys &env))
with actually #(keys &env) being equal to #ks
The question doesn't really explain what I want to do but I couldn't think of anything else.
I have an empty map in the outer let function in a piece of code, and an integer array.
I want to iterate through the integer array, perform a simple task, and keep appending the resulting map to the variables in the outer variables.
(let [a {} ;outer variables
b {}]
(doseq [x [1 2 3]]
(let [r (merge a {x (* x x)}) ;I want to append this to a
s (merge b {x (+ x x)})] ;and this to b
(println (str "--a--" r "--b--" s)))))
But as soon as I get out of doseq, my a and b vars are still empty. I get that the scope of a and b doesn't extend outside of doseq for it to persist any changes done from within and that they are immutable.
How do I calculate the values of a and b in such cases, please? I tried to extract the functionality of doseq into another function and calling let with:
(let [a (do-that-function)])
etc but even then I couldn't figure out a way to keep track of all the modifications within doseq loop to then send back as a whole.
Am I approaching this in a wrong way?
Thanks
edit
Really, what I'm trying to do is this:
(let [a (doseq [x [1 2 3]] {x (* x x)})]
(println a))
but doseq returns nil so a is going to be nil :-s
All variables in clojure are immutable. If you need a mutable state you should use atoms or refs.
But in your case you can simply switch from doseq to for:
(let [a (for [x [1 2 3]] {x (* x x)})]
(println a))
Here is an example of solving your problem with atoms:
(let [a (atom {})
b (atom {})]
(doseq [x [1 2 3]]
(swap! a assoc x (* x x))
(swap! b assoc x (+ x x)))
(println "a:" #a)
(println "b:" #b))
But you should avoid using mutable state as far as possible:
(let [l [1 2 3]
a (zipmap l (map * l l))
b (zipmap l (map + l l))]
(println "a:" a)
(println "b:" b))
The trick is to think in terms of flows of data adding to existing data making new data, instead of changing past data. For your specific problem, where a data structure is being built, reduce is typically used:
(reduce (fn [result x] (assoc result x (* x x))) {} [1 2 3])
hehe, I just noticed that "reduce" might seem confusing given that it's building something, but the meaning is that a collection of things is "reduced" to one thing. In this case, we give reduce an empty map to begin with, which binds to result in the fn, and each successive mapping over the collection results in a new result, which we add to again with assoc.
You could also say:
(into {} (map (fn [x] [x (* x x)]) [1 2 3]))
In your question you wanted to make multiple things at once from a single collection. Here's one way to do that:
(reduce (fn [[a b] x] [(assoc a x (* x x)) (assoc b x (+ x x))]) [{} {}] [1 2 3])
Here we used destructuring syntax to refer to our two result structures - just make a picture of the data [with [vectors]]. Note that reduce is still only returning one thing - a vector in this case.
And, we could generalize that:
(defn xfn [n fs]
(reduce
(fn [results x] (map (fn [r f] (assoc r x (f x x))) results fs))
(repeat (count fs) {}) (range n)))
=> (xfn 4 [* + -])
({3 9, 2 4, 1 1, 0 0} {3 6, 2 4, 1 2, 0 0} {3 0, 2 0, 1 0, 0 0})
The result is a list of maps. And if you wanted to take intermediate steps in the building of these results, you could change reduce to reductions. Generally, map for transforming collections, reduce for building a single result from a collection.
I would like to know how to increment by X amount a number, in other languages I used to do
foo += 0.1;
but I have not idea how it can be done in Clojure
Variables are immutable in Clojure. So you should not try to change the value of foo, but instead, "create" a new foo:
(def foo2 (+ foo 0.1))
...or, if in a loop, recur with a new value:
(loop [foo 5.0]
(when (< foo 9)
(recur (+ foo 0.1))))
...or, if foo is an atom, swap! it with a new value:
(def foo (atom 5.0))
(swap! foo (partial + 0.1))
I recommend you start by reading the rationale of Clojure.
Blacksad's answer covers defining vars so I would just like to add the other scopes in which you may wish to have a value that is incremented from another value:
within a function's local scope:
user> (defn my-function [x]
(let [y (inc x)
z (+ x y)]
[x y z]))
#'user/my-function
user> (my-function 4)
[4 5 9]
and If you want to build a value incrementally to make the process more clear:
user> (defn my-function [x]
(let [y (inc x)
z (+ x y)
z (+ z 4)
z (* z z)]
[x y z]))
#'user/my-function
user> (my-function 4)
[4 5 169]
This can make the process more presentable, though it is not a "way to get variables back" and is really only useful in limited contexts. This pattern is used in clojure.core's threading macros.
I have a datatype defined with defrecord, which contains two vectors:
(defrecord MyType [a b])
(def mytype (->MyType [1 2 3] [4 5 6]))
I want to have a function update both vectors and return a new MyType. The only way I can think of to do that is via nested assoc calls:
(defn mutate-mytype [mytype x y]
(assoc mytype :a (assoc (:a mytype) x y)
:b (assoc (:b mytype) x y)))
Example output:
user=> (mutate-mytype mytype 1 7)
#user.MyType{:a [1 7 3], :b [4 7 6]}
Question: Is there a better way to write that mutate-mytype method?
Your implementation is perfectly fine.
There are a few alternatives, e.g. you might consider using assoc-in and the -> threading operator:
(defn mutate-mytype [mytype x y]
(-> mytype
(assoc-in [:a x] y)
(assoc-in [:b x] y)))
This doesn't really have any advantages over your approach in this case, but it might make the code more readable if you had more deep nesting going on.