So i have a function that i am doing two if statements on, the first one appears to be working, but the second one is producing the error
ClassCastException java.lang.String cannot be cast to clojure.lang.IFn user/sort-maps (NO_SOURCE_FILE:1559)
The function passes in two Map "m1 + m2" and two strings "s1 s2"
the problem piece of code is :
(if-not (= (get map1 s2)(s1))
What i am trying to do is see if string "s1" equals the string from value at "map s2" but i keep getting that error. This is the function i have
(defn sort-maps [map1 map2 s2 s1]
(if-not (contains? map1 s2)
[(assoc map1 s2 s1) map2]
[map1 (assoc map2 s2 s1)])
(if-not (= (get map1 s2)(s1))
[(dissoc map2 (get map1 s2))]
[map1 (assoc map2 s2 s1)]))
My input:
"door" "rood" "odor" "pen" "list" "silt" "#"
My output i want would be:
{"enp" "pen"}
As i only want to return words that cannot be made up into any other word in the input
munk rightly pointed out to the source of your error: (s1) tells Clojure to invoke s1 as a function with no arguments. However, even after fixing this, your code is unlikely to do what you expect it to do.
This is the body of the function sort-maps (with munk's correction):
(if-not (contains? map1 s2)
[(assoc map1 s2 s1) map2]
[map1 (assoc map2 s2 s1)])
(if-not (= (get map1 s2) s1)
[(dissoc map2 (get map1 s2))]
[map1 (assoc map2 s2 s1)])
The first if-not statement is executed and the result (either a pair of updated map1 and map2 or a pair of map1 and updated map2) is thrown away. Since maps in Clojure are immutable, assoc isn't going to add a new entry into the existing map - a new map is created instead. So, this function body is completely equivalent to just
(if-not (= (get map1 s2) s1)
[(dissoc map2 (get map1 s2))]
[map1 (assoc map2 s2 s1)])
I am not sure what you are doing here, so can't help you further.
s1 is a string, but by wrapping it in parens, you're making a function call. A string isn't a function, so that's why you're seeing the type error.
You probably want (if-not (= (get map1 s2) s1))
But you seem to have a deeper misunderstanding. Clojure data structures are immutable. This means the following:
user=> (def my-map {:a 1 :b 2})
#'user/my-map
user=> (assoc my-map :c 3)
{:a 1, :b 2, :c 3}
user=> my-map
{:a 1, :b 2}
user=> (dissoc my-map :a 1)
{:b 2}
user=> my-map
{:a 1, :b 2}
So you can't just change a value in place like you can with ruby or some other language.
Related
I have a map like so:
{:a "some" :b (str :a " stuff")}
What I'm trying to do is to have the :b value of the map be "some stuff", but the above example doesn't work. I tried wrapping it in def;
(def foo {:a "some" :b (str (:a foo) " stuff")})
But that doesn't work either. How do I make this work?
You have to use a let here (either define the map or the value of a). You can not access the map while it is build up.
also, you can employ macros for this case (for fun and education). Like you can make up simple anaphoric macro to do the trick:
(defmacro make-map-ana [& keyvals]
`(-> {}
~#(map (fn [[k v]] `((fn [~'it] (assoc ~'it ~k ~v))))
(partition-all 2 keyvals))))
that is how you use it:
user> (make-map-ana :a "some"
:b (str (:a it) " stuff"))
;;=> {:a "some", :b "some stuff"}
that gets expanded to clojure code this way:
(-> {}
((fn [it] (assoc it :a "some")))
((fn [it] (assoc it :b (str (:a it) " stuff")))))
so it gets reflective, passing the context (namely it) downstream.
(make-map-ana :a :fun
:b it
:c it)
;;=> {:a :fun, :b {:a :fun}, :c {:a :fun, :b {:a :fun}}}
another way to write this macro, is to use the overriding in let bindings:
(defmacro make-map-ana [& keyvals]
`(let [~'it {}
~#(mapcat (fn [[k v]] ['it `(assoc ~'it ~k ~v)])
(partition-all 2 keyvals))]
~'it))
now (make-map-ana :a "some" :b (str (:a it) " stuff")) would expand into this:
(let [it {}
it (assoc it :a "some")
it (assoc it :b (str (:a it) " stuff"))]
it)
also producing the result you need
Well, as cfrick said, I don't think you can access a map while you are building it like you wrote in your second example.
You could build a simple function like the one bellow.
(defn merge-a-b [map] (assoc map :b (str (:a map) (:b map))))
It's also useful if you end with a vector of those maps, like:
(def x2 [{:a "some", :b " stuff"} {:a "some-other", :b " stuff"}])
You can just use the map build-in in Clojure and run it like:
(map merge-a-b x2)
({:a "some", :b "some:a stuff"} {:a "some-other", :b "some-other stuff"})
I am new to Clojure. I am trying to use java hashmap in clojure. I am passing a java hashmap to Clojure. The map is- {0=Goa, 1=Delhi, 2=Mumbai}. When I am trying to use the clojure functions on this map I am not getting the expected output. In contrast to this when I am iterating over this map it is giving the expected output.
Example
(println(get map 0)) is giving nil
(doseq [[key value] map
(println value)) is giving the expected output.
Output-Goa
Delhi
Mumbai
Can somebody please expain me why is this happening?
You really should google a bit to find pre-existing answers like this one: Clojure: working with a java.util.HashMap in an idiomatic Clojure fashion
You can then see a simple answer:
(def data {:a 1 :b 2 :c 3})
(def java-map (java.util.HashMap. data))
(def clj-map (into {} java-map))
which gives us:
java-map => <#java.util.HashMap {:b 2, :c 3, :a 1}>
clj-map => <#clojure.lang.PersistentArrayMap {:b 2, :c 3, :a 1}>
and looping:
(doseq [[k v] clj-map]
(println (format "key=%s val=%s" k v)) )
with result:
key=:b val=2
key=:c val=3
key=:a val=1
I think your problem is that your map is named "map" which is also a Clojure function. Try it like this:
(def my-map {0 "Goa" 1 "Delhi" 2 "Mumbai"})
Which then will work like this:
(println (get my-map 0))
Note that it still returns nil, since there is nothing else after the (println) form but it does print the value of the 0 in the map, which is "Goa".
(def input-map {0 "Goa" 1 "Delhi" 2 "Mumbai"})
(map (fn[[k v]] (print "key " k " value " k)) input-map)
[[k v]] for function let you access key and value for each entry
(map print input-map)
here map entry will be passed as parameter to print
I am totally new to clojure.
I have a JSON like: { "1": true, "2": false, "3": true, "4": false }
I want to create an array of keys for which the value is true in clojure. In this example the array should be ["1", "3"].
Please help me. Any help would be appreciated.
there are also couple of short and simple snippets for that:
user> (filter m (keys m))
;;=> ("1" "3")
user> (keep (fn [[k v]] (when v k)) m)
;;=> ("1" "3")
user> (for [[k v] m :when v] k)
;;=> ("1" "3")
If you're fine with using a vector instead of an array (since you're usually using vectors in Clojure anyway), you can do something like.
(defn keys-for-truthy-vals [m]
(->> m (filter val) (mapv key)))
Note The mapv is only so the map call returns a vector. If you want a seq, just use map.
The same as already provided, just staying in maps.
(keys (filter val m))
If your map is a Something like (->> (filter (fn [[k v]] v) a) (map (fn [[k v]] k))) will work. You can't do it with just a map because you need to drop certain values, so there will need to be some reducing or filtering.
There is built-in function in the Tupelo library for this:
(submap-by-vals map-arg keep-vals & opts)
Returns a new map containing entries with the specified vals. Throws for missing vals,
unless `:missing-ok` is specified. Usage:
(submap-by-vals {:a 1 :b 2 :A 1} #{1 } ) => {:a 1 :A 1}
(submap-by-vals {:a 1 :b 2 :A 1} #{1 9} :missing-ok ) => {:a 1 :A 1}
You could then just use the keys function on the resulting map.
Maybe this?
(->> foo (filter second) keys)
where foo is a map.
Say I have a board like this
(def board {:a 10 :b 12})
And a list of functions like this
(def funcs [(assoc board :a 2)
(assoc board :b 4)
(assoc board :a (inc (get board :a)))])
How would I go about applying each operation in the list to my board, having it update each time in a functional fashion.
Evaluating funcs in my repl, gives a list of return values after calling each function, but the board itself remains unchanged each time
user=> funcs
[{:a 2, :b 12} {:a 10, :b 4} {:a 11, :b 12}
Ideally I'd like the value of the board to update each time a function is ran
so after running the all commands the final state of the board should be:
{:a 3 :b 4}
I'm aware this is possible using tail recursion but I'd like to avoid doing so as I'm almost certain a combination of reduce/apply/map will do the trick
One of the defining traits of clojure is that its data structures are immutable. That means that board will never change, functions that operate on data structures return modified copies of the data structure. So what you've done in funcs is make a vector of three different boards, the original board with a fuction applied.
Usually what you want is to apply a bunch of functions to some initial value, where each function takes the returned value of the function before, then use the returned value for something. Usually passing it around in function parameters.
;; First of all, there's a function for that
(assoc board :a (inc (get board :a)))
;; The function update takes a map and a key and a function
;; It applies the function to value currently at key,
;; then sets key in the retuned "copy" of the map to be the return value of the function.
;; Equivalent to the above
(update board :a inc)
If you want an updated board with these functions applied, you need to to pass the return value through the functions, because the original board never changes, they all just return updated copies of their input.
(def updated-board
;; The innermost forms are evaluated first.
(update (assoc (assoc board :a 2) :b 4) :a inc))
This can be made more readable by using the -> or "thread first" macro. It takes an initial value and forms which are missing the first argument, then rewrites the code to "thread" the return value of each one as the first argument to the next.
(def updated-board-threaded
(-> board
(assoc :a 2)
(assoc :b 4)
(update :a inc)))
;; You can expand the macro to see for yourself
;; that the two examples are exactly equivalent.
(macroexpand-1 '(-> board
(assoc :a 2)
(assoc :b 4)
(update :a inc)))
;;=> (update (assoc (assoc board :a 2) :b 4) :a inc)
This is the way to "think in clojure", functions usually just take immutable values and return other immutable values.
But sometimes you need something mutable, and clojure delivers this in the form of atoms. An atom can be thought of as a mutable box that contains an immutable value.
It uses the functions swap! and reset! to apply controlled mutation. And the function deref to get the current value.
(def board (atom {:a 10, :b 12}))
;; I'll define a function that takes a board and returns an updated version of it.
(defn do-stuff-with-board [b]
(-> b
(assoc :a 2)
(assoc :b 4)
(update :a inc)))
;; Get the current value of board.
(deref board) ;;=> {:a 10, :b 12}
;; Swap takes an atom and a function and
;; sets the value of the atom to be the return value of the function
(swap! board do-stuff-with-board)
;; Now the mutable board atom contains a new immutable value.
(deref board) ;;=> {:a 3, :b 4}
;; derefing an atom is a very usual operation, so there's syntax sugar for it
;; Equivalent to (deref board)
#board ;;=> {:a 3, :b 4}
reset! sets the value of board to be another value, like = in "normal" languages. It's not usually idiomatic to do this as it kinda says to the reader that the new value of the atom has nothing to do with the old one, but clojure is pragmatic, and sometimes it's what you need.
(reset! board "And now for something completely different.")
;; The value is now a string.
#board ;;=> "And now for something completely different."
As an aside. The data structures are not actually deep copies of each other, there is magic behind the scenes to make it almost as efficient as updating the data structure in place, but from the perspective of the programmer they are equivalent to deep copies in other languages.
I'd like to suggest a different approach to #madstap's fine answer.
In ...
(def funcs [(assoc board :a 2)
(assoc board :b 4)
(assoc board :a (inc (get board :a)))])
... the elements such as (assoc board :b 4) are not functions: they are function calls, which, as #madstap points out, fail to modify whatever board refers to.
We can, without too much trouble, turn them into proper functions:
(def funcs [(fn [board] (assoc board :a 2))
(fn [board] (assoc board :b 4))
(fn [board] (assoc board :a (inc (get board :a))))])
The boards here are locals. Any distinct identifier would do as well:
(def funcs [(fn [b] (assoc b :a 2))
(fn [b] (assoc b :b 4))
(fn [b] (assoc b :a (inc (get b :a))))])
We can write a function to compose them:
(defn compose [fs]
(fn [x] (reduce (fn [a f] (f a)) x fs)))
This is a simplified version of the standard comp. It applies the functions first to last instead of last to first.
Now, for example, if
(def board {:a 10 :b 12})
... then
((compose funcs) board)
;{:a 3, :b 4}
Furthermore, we can modify compose to show the chain of results:
(defn compositions [fs]
(fn [x] (reductions (fn [a f] (f a)) x fs)))
((compositions funcs) board)
;({:a 10, :b 12} {:a 2, :b 12} {:a 2, :b 4} {:a 3, :b 4})
Notice that compose and compositions are completely generic - they just do stuff with functions.
Is there a way to destructure a key value pair ? I have a function which take a map as a parameter, I would like to extract the value of both the key and the value in the params itself. How do I do that ?
I can do the following with a vector -
((fn [[a b]] (str a b)) [a b])
How do I do the same / similar with map -
((fn[{k v}] (str k v)) {k v})
Thanks,
Murtaza
map destructuring in functions arg lists is designed for extracting certain keys from a map and giving them names like so:
core> (defn foo [{my-a :a my-b :b}] {my-a my-b})
core/foo
core> (foo {:a 1 :b 2})
{1 2}
i recommend this tutorial. It is a little hard to give a direct equivalent to ((fn[{k v}] (str k v)) {k v}) because the map could have many keys and many values so the destructuring code would be unable to tell which key and value you where looking for. Destructuring by key is easier to reason about.
If you want to arbitrarily choose the first entry in the map you can extract it and use the list destructuring form on a single map entry:
core> (defn foo [[k v]] {v k})
#'core/foo
core> (foo (first {1 2}))
{2 1}
in this example the list destructuring form [k v] is used because first returns the first map entry as a vector.
There are shortcuts available for destructuring maps. For example, if you're looking for specific keys, then you don't have to type out name1 :key1 name1 :key2...
e.g.
main=> (defn fbb [{:keys [foo bar baz]}] (+ foo bar baz))
#'main/fbb
main=> (fbb {:foo 2 :bar 3 :baz 4})
9
instead of...
(defn fbb [{foo :foo bar :bar baz :baz}] (+ foo bar baz))
If your map keys are strings, you can say :strs instead of :keys and if they are symbols you can use :syms.
user=> (for [x (hash-map :a 1 :b 2 :c 3)] (str (first x) " " (second x)))
(":a 1" ":c 3" ":b 2")