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
Related
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.
I am trying to do something similar in Clojure:
# Increase the count of a feature/category pair
def incf(self,f,cat):
self.fc.setdefault(f,{})
self.fc[f].setdefault(cat,0)
self.fc[f][cat]+=1
Does anybody have idea?
I think a close parallel is fnil which takes a function and some default argument value(s), then returns a function that will use the default value if called with nil argument(s):
(defn incf [fc f cat]
(update-in fc [f cat] (fnil inc 0)))
(incf {} :feature-foo :category-bar)
=> {:feature-foo {:category-bar 1}}
Here we use update-in to update a nested value in the input map, and use fnil to set the default value zero to be incremented if it doesn't exist.
First, you cannot mutate a hash map in Clojure, so there is no exact counterpart for setdefault.
However, if you want to update a nested map increasing the given value (or set to 1, if it is null), you can leverage the fact that clojure.core/get can accept an optional third argument which is the default value (and also, an assoc on nil creates a map):
(defn incf [m cat f]
(let [val (get-in m [cat f] 0)]
(assoc-in m [cat f] (inc val))))
(incf {:my-cat {:a 1}} :my-cat :a) ; returns {:my-cat {:a 2}}
(incf {:my-cat {}} :my-cat :a) ; returns {:my-cat {:a 1}}
(incf {} :my-cat :a) ; returns {:my-cat {:a 1}}
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")
Say I have a map of this form:
(def m {:a "A" :b "B"})
and I want to do something if :a and :b are both not nil, I can do:
(if-let [a (:a m)]
(if-let [b (:b m)]
... etc ))
or
(if (and (:a m) (:b m))
(let [{a :a b :b} m]
... etc ))
or even
(if (every? m [:a :b])
(let [{a :a b :b} m]
... etc ))
Is there a neater (ie one-line) way to achieve this?
I think a macro may be necessary here to create the behavior you want. I have never written one (yet) but the following representation suggests to me that this might be fairly straightforward:
(let [{:keys [a b]} m]
(when (every? identity [a b])
(println (str "Processing " a " and " b))))
Using the :keys form of destructuring binding and every? enables a single specification of a vector of keys to destructure and check, and the bound locals are available in a following code block.
This could be used to make a macro such as (when-every? [keys coll] code-with-bindings)
I may update this answer with the macro code if I can take the time to work out how to do it.
You could use map destructuring -- a useful feature of Clojure. This also exploits the facts that and is short-circuiting, and any key in the first map not found in the second map gets nil, a falsy value:
(let [{a :a b :b} {:a 1 :b "blah"}]
(and a b (op a b)))
Okay, so it's two lines instead of one .... also this doesn't distinguish between nil and other falsy values.
not-any? is a nice shortcut for this:
user> (not-any? nil? [(m :a) (m :b)])
true
user> (not-any? nil? [(m :a) (m :b) (m :d)])
false
user>
I am not quite sure what you want to do if the keys have non-nil values or whether you want non-nil keys or values returned. So, I just solved it for non-nil keys being returned.
You'd use the following as an intermediate step as part of a final solution.
I'm showing all the steps I used, not to be pedantic, but to provide a complete answer. The namespace is repl-test. It has a main associated with it.
repl-test.core=> (def m {:a "A" :b "B" :c nil})
#'repl-test.core/m
repl-test.core=> (keys m)
(:a :c :b)
and then finally:
; Check key's value to determine what is filtered through.
repl-test.core=> (filter #(if-not (nil? (%1 m)) (%1 m)) (keys m) )
(:a :b)
By the way I found an ugly one-liner, which works because and returns the last thing in its argument list if they're all true:
(if-let [[a b] (and (:a m) (:b m) [(:a m)(:b m)])]
(println "neither " a " nor " b " is falsey")
(println "at least one of " a " or " b " is falsey"))