What is the difference between the functions seq? sequential? and coll?
I found some information scattered throughout the internet, but I think it would be better to centralize that information here.
seq? is a predicate that returns true if it's argument implements ISeq interface, which is to say it provides the methods first,rest,cons. See http://clojure.org/sequences.
(seq? [1 2])
false
(seq? (seq [1 2]))
true
sequential? is a predicate that returns true if it's argument implements Sequential interface. Sequential is a marker interface (no methods) and is a promise that the collection can be iterated over in a defined order (e.g. a list, but not a map).
(sequential? [])
true
(sequential? {})
false
coll? is a predicate that returns true if its argument implments IPersistentCollection. So for example the clojure data structures would return true, whereas native java data structures would not:
(coll? {:a 1})
true
(coll? (java.util.HashMap.))
false
seq? is true for any sequence.
sequential? is true for any sequential (not associative)
collection.
coll? is true for any Clojure collection.
seq? implies sequential? implies coll?
=> ((juxt seq? sequential? coll?) ()) ; [true true true]
=> ((juxt seq? sequential? coll?) []) ; [false true true]
=> ((juxt seq? sequential? coll?) #{}); [false false true]
Inaccurate: sequential? is related to the others purely by convention - see Kevin's answer.
Related
I want to maintain a collection of channels, with the ability to add and remove channels. Is the equality defined so I can conj and disj correctly?
In other words, will this always work?
=> (def chan-collection (atom #{}))
=> (def my-chan-1 (chan))
=> (def my-chan-2 (chan))
=> #chan-collection
#{}
=> (swap! chan-collection conj my-chan-1)
=> #chan-collection
#{#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel#6ec3a2f6>}
=> (swap! chan-collection conj my-chan-2)
=> #chan-collection
#{#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel#382830a1>
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel#6ec3a2f6>}
=> (swap! chan-collection disj my-chan-1)
=> #chan-collection
#{#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel#382830a1>}
=> (swap! chan-collection disj my-chan-2)
=> #chan-collection
#{}
Yes this is true, and changing it would break everything.
Channels are identical? if they are the same chan object, and therefore are equal in all cases. All other comparisons of chans are explicitly not equal, and this is good for you. You want removal to remove the exact chan you ask to be removed rather than some equivalent chan with the same contents. So it's fortunate that chans that are not identical are also not equal
user> (= (chan) (chan))
false
user> (identical? (chan) (chan))
false
user> (identical? my-chan-1 (chan))
false
user> (identical? my-chan-1 my-chan-1)
true
user>
user> (= my-chan-1 my-chan-1)
true
In the general "Clojure world" this same property is true of all things that are Identities rather than values. Identities have values that change over time so it doesn't make sense to say that two identities are equal if they happen to contain the same value at the moment you ask, even though this may only be true for you and never for anyone else. comparing the values in identities makes much more sense. for example like chans, atoms with the same values are also not equal and this is a fundamental property of clojure that will never change.
user> (let [a (atom 1)]
(= a a))
true
user> (= (atom 1) (atom 1))
false
Provided you want to remove them by giving the exact chan you want removed as an argument to disj, as you are doing above, rather than some other notion like "remove the channel with 42 in it"
If we do the same setup:
user> (require '[clojure.core.async :refer [<! <!! >! chan]])
nil
user> (def chan-collection (atom #{}))
#'user/chan-collection
user> (def my-chan-1 (chan))
#'user/my-chan-1
user> (def my-chan-2 (chan))
#'user/my-chan-2
user> (swap! chan-collection conj my-chan-1 my-chan-2)
#{#object[clojure.core.async.impl.channels.ManyToManyChannel 0x35b61c71 "clojure.core.async.impl.channels.ManyToManyChannel#35b61c71"] #object[clojure.core.async.impl.channels.ManyToManyChannel 0x240e86d5 "clojure.core.async.impl.channels.ManyToManyChannel#240e86d5"]}
and then ask to have "the empty chan" removed:
user> (swap! chan-collection disj (chan))
#{#object[clojure.core.async.impl.channels.ManyToManyChannel 0x35b61c71 "clojure.core.async.impl.channels.ManyToManyChannel#35b61c71"] #object[clojure.core.async.impl.channels.ManyToManyChannel 0x240e86d5 "clojure.core.async.impl.channels.ManyToManyChannel#240e86d5"]}
we can verify that it does nothing.
I'm trying get a clojure function to detect if the value passed is a map.
For example,
user=> (if-map {:foo 1}) ;Should return true
true
user=> (if-map "hello") ;Returns false
false
Is there a pre-built function serving this already?
Yes, map? is the inbuilt function
(map? {:a 1})
=> true
(map? [1])
=> false
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.
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.
I am trying to implement a function that takes a number n and returns a list of lists of booleans that contains all possible combinations of n booleans. The output of e.g. (make-bools 3) should look like
[[false false false]
[false false true ]
[false true false]
[false true true ]
[true false false]
[true false true ]
[true true false]
[true true true ]]
I thought of converting the numbers from 0 to (2^n) - 1 to a binary format and use bit-test to make a list of booleans, finally chaining all those lists. But that seems quite clumsy to me and I suppose there must be a more elegant solution.
I don't know if it's considered 'cheating' to use an existing library, rather than respond to the algorithmic details of your question, but Clojure-contrib has a set of common combinatorial functions that are useful for calculating permutations:
(require '[clojure.contrib.combinatorics :as comb])
(defn make-bools [n]
(apply comb/cartesian-product (repeat n [true false])))
http://richhickey.github.com/clojure-contrib/combinatorics-api.html
for also works fine
(let [bools [false true]]
(for [x bools y bools z bools] [x y z]))
If you're still looking for a recursive, from-scratch solution (if only to study), here's one that implements a pattern that's often useful for recursively building "paths" through tree structures:
(let [bools [true false]]
(fn combs [n]
(if (zero? n)
[[]]
(for [smaller (combs (dec n))
b bools]
(cons b smaller)))))
In this case, the "tree" is imaginary (a series of true/false choices), but the same techniques apply.