In clojure, what is the exact behaviour of identical? - clojure

I am very surprised by the behaviour of identical? in clojure.
(def a (map identity [:a :b]))
(identical? (rest a) (rest a)); false
Any idea why identical? returns false?

identical?:
Tests if 2 arguments are the same object
Since rest creates a new seq object on each invocation, its results are not identical?. The following, however, is:
(def r (rest (map identity [:a :b])))
(identical? r r) ;; => true
Update: As #mfikes pointed out, rest does not always create a new seq. It calls ISeq.more() internally which is implemented per seq type and might yield different results for lists, vectors, lazy seqs, etc.:
(->> [(map identity [:a :b])
(vector :a :b)
(list :a :b)]
(map #(identical? (rest %) (rest %))))
;; => [false false true]

identical? is the object equality predicate. It returns true if its arguments are the same object/primitive.
Use = over identical?.
identical? is the correct tool when semantics depend on pointer equality, such as testing for an end-of-file sentinel value.
Never use identical? to compare Clojure data structures. Even keywords don't guarantee identical? behaves correctly.

Related

Clojure loop collection

I want to know if this is the right way to loop through an collection:
(def citrus-list ["lemon" "orange" "grapefruit"])
(defn display-citrus [citruses]
(loop [[citrus & citruses] citruses]
(println citrus)
(if citrus (recur citruses))
))
(display-citrus citrus-list)
I have three questions:
the final print displays nil, is it ok or how can avoid it?
I understand what & is doing in this example but I don´t see it in other cases, maybe you could provide a few examples
Any other example to get the same result?
Thanks,
R.
First of all your implementation is wrong. It would fail if your list contains nil:
user> (display-citrus [nil "asd" "fgh"])
;;=> nil
nil
And print unneeded nil if the list is empty:
user> (display-citrus [])
;;=> nil
nil
you can fix it this way:
(defn display-citrus [citruses]
(when (seq citruses)
(loop [[citrus & citruses] citruses]
(println citrus)
(if (seq citruses) (recur citruses)))))
1) it is totally ok: for non-empty collection the last call inside function is println, which returns nil, and for empty collection you don't call anything, meaning nil would be returned (clojure function always returns a value). To avoid nil in your case you should explicitly return some value (like this for example):
(defn display-citrus [citruses]
(when (seq citruses)
(loop [[citrus & citruses] citruses]
(println citrus)
(if (seq citruses) (recur citruses))))
citruses)
user> (display-citrus citrus-list)
;;=> lemon
;;=> orange
;;=> grapefruit
["lemon" "orange" "grapefruit"]
2) some articles about destructuring should help you
3) yes, there are some ways to do this. The simplest would be:
(run! println citrus-list)
Answering your last question, you should avoid using loop in Clojure. This form is rather for experienced users that really know what they do. In your case, you may use such more user-friendly forms as doseq. For example:
(doseq [item collection]
(println item))
You may also use map but keep in mind that it returns a new list (of nils if your case) that not sometimes desirable. Say, you are interested only in printing but not in the result.
In addition, map is lazy and won't be evaluated until it has been printed or evaluated with doall.
For most purpose, you can use either map, for or loop.
=> (map count citrus-list)
(5 6 10)
=> (for [c citrus-list] (count c))
(5 6 10)
=> (loop [[c & citrus] citrus-list
counts []]
(if-not c counts
(recur citrus (conj counts (count c)))))
[5 6 10]
I tend to use map as much of possible. The syntax is more concise, and it clearly separates the control flow (sequential loop) from the transformation logic (count the values).
For instance, you can run the same operation (count) in parallel by simply replacing map by pmap
=> (pmap count citrus-list)
[5 6 10]
In Clojure, most operations on collection are lazy. They will not take effect as long as your program doesn't need the new values. To apply the effect immediately, you can enclose your loop operation inside doall
=> (doall (map count citrus-list))
(5 6 10)
You can also use doseq if you don't care about return values. For instance, you can use doseq with println since the function will always return nil
=> (doseq [c citrus-list] (println c))
lemon
orange
grapefruit

How to print each elements of a hash map list using map function in clojure?

I am constructing a list of hash maps which is then passed to another function. When I try to print each hash maps from the list using map it is not working. I am able to print the full list or get the first element etc.
(defn m [a]
(println a)
(map #(println %) a))
The following works from the repl only.
(m (map #(hash-map :a %) [1 2 3]))
But from the program that I load using load-file it is not working. I am seeing the a but not its individual elements. What's wrong?
In Clojure tranform functions return a lazy sequence. So, (map #(println %) a) return a lazy sequence. When consumed, the map action is applied and only then the print-side effect is visible.
If the purpose of the function is to have a side effect, like printing, you need to eagerly evaluate the transformation. The functions dorun and doall
(def a [1 2 3])
(dorun (map #(println %) a))
; returns nil
(doall (map #(println %) a))
; returns the collection
If you actually don't want to map, but only have a side effect, you can use doseq. It is intended to 'iterate' to do side effects:
(def a [1 2 3])
(doseq [i a]
(println i))
If your goal is simply to call an existing function on every item in a collection in order, ignoring the returned values, then you should use run!:
(run! println [1 2 3])
;; 1
;; 2
;; 3
;;=> nil
In some more complicated cases it may be preferable to use doseq as #Gamlor suggests, but in this case, doseq only adds boilerplate.
I recommend to use tail recursion:
(defn printList [a]
(let [head (first a)
tail (rest a)]
(when (not (nil? head))
(println head)
(printList tail))))

why are `disj` and `dissoc` distinct functions in Clojure?

So far as I've seen, Clojure's core functions almost always work for different types of collection, e.g. conj, first, rest, etc. I'm a little puzzled why disj and dissoc are different though; they have the exact same signature:
(dissoc map) (dissoc map key) (dissoc map key & ks)
(disj set) (disj set key) (disj set key & ks)
and fairly similar semantics. Why aren't these both covered by the same function? The only argument I can see in favor of this is that maps have both (assoc map key val) and (conj map [key val]) to add entries, while sets only support (conj set k).
I can write a one-line function to handle this situation, but Clojure is so elegant so much of the time that it's really jarring to me whenever it isn't :)
Just to provide a counterpoise to Arthur's answer: conj is defined even earlier (the name conj appears on line 82 of core.clj vs.1443 for disj and 1429 for dissoc) and yet works on all Clojure collection types. :-) Clearly it doesn't use protocols – instead it uses a regular Java interface, as do most Clojure functions (in fact I believe that currently the only piece of "core" functionality in Clojure that uses protocols is reduce / reduce-kv).
I'd conjecture that it's due to an aesthetic choice, and indeed probably related to the way in which maps support conj – were they to support disj, one might expect it to take the same arguments that could be passed to conj, which would be problematic:
;; hypothetical disj on map
(disj {:foo 1
[:foo 1] 2
{:foo 1 [:foo 1] 2} 3}
}
{:foo 1 [:foo 1] 2} ;; [:foo 1] similarly problematic
)
Should that return {}, {:foo 1 [:foo 1] 2} or {{:foo 1 [:foo 1] 2} 3}? conj happily accepts [:foo 1] or {:foo 1 [:foo 1] 2} as things to conj on to a map. (conj with two map arguments means merge; indeed merge is implemented in terms of conj, adding special handling of nil).
So perhaps it makes sense to have dissoc for maps so that it's clear that it removes a key and not "something that could be conj'd".
Now, theoretically dissoc could be made to work on sets, but then perhaps one might expect them to also support assoc, which arguably wouldn't really make sense. It might be worth pointing out that vectors do support assoc and not dissoc, so these don't always go together; there's certainly some aesthetic tension here.
It's always dubious to try to answer for the motivations of others, though I strongly suspect this is a bootstrapping issue in core.clj. both of these functions are defined fairly early in core.clj and are nearly identical except that they each take exactly one type and call a method on it directly.
(. clojure.lang.RT (dissoc map key))
and
(. set (disjoin key))
both of these functions are defined before protocals are defined in core.clj so they can't use a protocol to dispatch between them based on type. Both of these where also defined in the language specification before protocols existed. They are also both called often enough that there would be a strong incentive to make them as fast as possible.
(defn del
"Removes elements from coll which can be set, vector, list, map or string"
[ coll & rest ]
(let [ [ w & tail ] rest ]
(if w
(apply del (cond
(set? coll) (disj coll w)
(list? coll) (remove #(= w %) coll)
(vector? coll) (into [] (remove #(= w % ) coll))
(map? coll) (dissoc coll w)
(string? coll) (.replaceAll coll (str w) "")) tail)
coll)))
Who cares? Just use function above and forget about the pasts...

Checking validity of all clojure values in a map

Is there a clean, idiomatic way to check that all the values of a map are not empty or 0.
If for instance I have the following map
{"id" 10 "Department" "UI Design" "managerid" 4}
What's the cleanest way to iterate over the values of the map and make sure the strings are not empty ("") or nil and the ints/longs are not 0 or nil.
Essentially I'm trying to validate some input before I commit it to the DB. I know I could use libraries like Prismatic/schema but for now I'd like to know how it could be achieved without this.
This map only contains strings and ints/longs but it could contain other types.
Is there a generic way of doing this?
Multimethods can provide elegant solution for given problem:
; for now dispatch is based only on value type
(defmulti valid? (fn [[k v]] (class v)))
(defmethod valid? java.lang.Long [[_ value]] (not (zero? value)))
(defmethod valid? java.lang.String [[_ value]] (not (empty? value)))
(defmethod valid? nil [_] false)
(defmethod valid? :default [_] true) ; valid for rest cases
To check whole map:
(every? valid? your-map)
Examples:
(every? valid? {:a 1 :b 0}) ; false
(every? valid? {:a 1 :b 1}) ; true
(every? valid? {:a 1 :b ""}) ; false
(every? valid? {:a 1 :b "a"}) ; true
(every? valid? {:a 1 :b "a" :c []}) ; true
Few notes:
(not (empty? value)) can be replaced to (not-empty value) or (seq value), but in both cases full value of string will be returned instead of boolean (which still will evaluate to true of course).
You cannot check number or string for nil because nil has its own type. In example above all nil values are considered as invalid. If for some keys nils are acceptable - dispatch function (fn [[k v]] (class v)) should be changed to also take key into account.
This solution is a bit longer than a simple function like
(defn valid? [[k v]]
(cond (string? v) (not (empty? v))
...
:else true))
but it is more maintainable and extensible.
EDIT. As mentioned in comments, idiomatic way is to use (seq coll) instead of (not (empty? coll)) because empty? is defined like (not (seq coll)). You may still want to keep (not (empty? coll)) check to make validation code more explicit and obvious.

Non-macro versions of clojure "and" and "or"

Are there non-macro versions of and and or in Clojure?
Update: In this case I don't care about the short circuiting.
or
The function some "Returns the first logical true value of (pred x) for any x in coll, else nil."
So you could use (some identity coll) for or. Note that its behaviour will differ from or when the last value is false: it will return nil where or would return false.
and
If you don't need to know the value of the last form in the coll vector, you can use (every? identity coll) for and. This will differ from the behaviour of the and macro in that it returns true if all of its arguments are truthy. See larsmans' answer if you need the result of the last form.
Let land stand for "logical and", then they're trivial to define:
(defn land
([] true)
([x & xs] (and x (apply land xs))))
Or, slightly closer to the standard and behavior:
(defn land
([] true)
([x] x)
([x & xs] (and x (apply land xs))))
And similarly for or.
This actually came up as a topic on clojure-dev recently. Rich Hickey ultimately concluded they should be added to core for 1.3 as every-pred and any-pred (logged as CLJ-729). I think further discussions there have led them to now be called every-pred (the and variant) and some-fn (the or variant). The final version was just recently committed to master.
If you mean functions: no, and they cannot be. The reason is that function forms always evaluate all their arguments before applying the function to their value. You do not want that here.
Most cases where you want this there is a more idiomatic way to do it, but just an exercise, it is possible to defer evaluation by thunking. Thunk your expressions and give them to logical operators that evaluate the the thunk when needed, using the standard and/or:
(defn &&* [& fns]
(cond (= 1 (count fns)) ((first fns))
:otherwise
(and ((first fns)) (apply &&* (next fns)))))
(defn ||* [& fns]
(cond (= 1 (count fns)) ((first fns))
:otherwise
(or ((first fns)) (apply ||* (next fns)))))
Example use:
(map
(partial apply &&*)
(map (partial map constantly) ;; thunk all of these values
[["yes" "no"]
[false true]
[true "something"]
[true "something" "false"]]))
("no" false "something" "false")
Another Example:
(defmacro thunks
"convert expressions into thunks to prevent advance evaluation"
[& exprs]
(let [fns# (map (fn [e] `(fn [] ~e)) exprs)]
(cons 'vector fns#)))
(apply ||* (thunks (+ 1 2) false (* 1 5)))
3
(apply &&* (thunks (+ 1 2) false (* 1 5)))
false
(apply &&* (thunks (+ 1 2) (* 1 5)))
5