Just starting out with core.logic, version "0.8.11":
(q/run* [q]
(q/fresh [a]
(q/membero a [2 3]))
(q/membero q [1]))
I don't understand the result: (1 1).
My understanding is that I create another variable a with fresh, which can take a value of 2 or 3.
And q can take a value of 1. Therefore I was expecting to see something like: (1), or (1 2 1 3), or maybe ([1 2] [1 3]) or even ({:q 1 :a 2} {:q 1 :a 3}), but not the actual result.
Another example:
(q/run* [q]
(q/fresh [a]
(q/membero a [1 2 3])
(q/membero q [3 4 5])
(q/== a q)))
;; make sense to me, returns (3)
(q/run* [q]
(q/fresh [a]
(q/membero a [1 2 3]))
(q/membero q [3 4 5]))
;; does not make sense to me, returns (3 4 3 5 4 3 5 4 5)
;; I was expecting `(3 4 5)`
Could someone explain what is happening here?
core.logic can be viewed a search algorithm, searching for possible ways to assign values to all the relevant variables that don't cause a conflict. It has a lot of very smart pruning techniques so that it doesn't search subtrees that are known to be no good, but basically it is a search.
It found two ways to assign variables that satisfy your query:
a=2, q=1
a=3, q=1
So it is returning two results. But you only ask about q (that's what the argument to run* is, the set of variables you want to know the values of), and q is the same in both of those assignments, so you see the same result (1) twice. You should not in general assume that results from run* will be distinct, unless you have gone to some effort to make them so.
Likewise in your last example, there are three values you could assign to q, and each of them works for any of the three values you could assign to a, so you get 3*3=9 results, with each q value repeated three times. The order these results are returned in is (from your perspective) arbitrary; really they are ordered in a way that helps core.logic prevent getting deadlocked in other, more complicated programs. You could see all the a,q pairs if you wanted, by writing instead (q/run* [a q] ...).
Related
I am in the second chapter of the Programming Clojure book, and I came across this paragraph -
Because Clojure data structures are immutable and implement hashCode
correctly, any Clojure data structure can be a key in a map.
I cannot understand how the feature mentioned in the above quote would be advantageous.
I would appreciate it if someone could help me understand this using an example or point me to the right resources.
This can be useful when forming a data structure that has composite keys i.e. keys that consist of more than one piece of information.
As a simple example, say we have a graph with vertices :a :b and :c and we wish to have a data structure which enables lookup of the cost metric associated with any edge. We can use a Clojure map where each key is a set:
(def cost {#{:a :b} 5
#{:b :c} 6
#{:c :a} 2})
We can now look up the cost associated with any edge:
(get cost #{:c :b}) ; => 6
In order to answer your question there are two things we need to discuss:
Hash Tables
Value vs Reference
In a hash table (and I'm grossly oversimplifying here) you take a "key" and you run it through a hashing function that converts that key in a unique* identifier that is then associated with an address in memory which holds a particular "value". This is the underlying abstraction for higher-level associative data structures like Clojure maps or Python dictionaries: you give me the key, I hash it, look up the address, give you back the thing.
In order for this scheme to work, the same key has to always hash to the same value for some definition of "same", otherwise you couldn't get the thing back out of the data structure.
In Java (and many other languages) the definition of "same" boils down to reference:
public class Foo {
int x = 5;
public static void main(String[] args) {
Foo myObj = new Foo();
Foo myOtherObj = new Foo();
myObj == myOtherObj; // false
myObj.x = 6;
myObj == myObj; // true
}
}
Even though myObj and myOtherObj both hold the value 5 at the point of comparison, they are not equal according to the rules of Java, because they are different references. That last comparison, which looks non-sensical if you've never worked in a different model, highlights the problem: when we create myObj it has a value of 5, but at one point in time it has a value of 6. Is it still the same? Again, Java says yes.
And when we get to hashing something that is a potential key for a hash table that distinction matters: how do we maintain a consistent thing to feed the hash function? Is it the value (x) the container holds or the container (Foo instance)?
Python takes an interesting approach here:
ls = [1, 2] # list
tp = (1, 2) # tuple
st = set() # empty set
st.add(tp) # fine
st.add((1, 2)) # still only has 1 element, (1, 2) == (1, 2)
st.add(ls) # Error: unhashable type list!
In Python, you can't use mutable objects as set members or dictionary keys, because they are saying "the meaning of this thing changes" so it is unsuitable for a hashed key. But you can use any immutable type as a hash key (even an immutable container). Note that (1, 2) == (1, 2), unlike in Java where two containers holding the same values are still compared on reference. Python compares mutable types by reference, but immutable types by value.
But in Clojure, everything** is immutable. Everything can be used as a hash key, because everything has a consistent value through time that can be fed to the hash function:
(def x [1 2])
(def y { x 5 })
(get y x) ; 5
(get y [1 2]) ; 5
When we lookup the vector bound to x in the map bound to y we get 5, since vectors are immutable we don't have to worry about identity. We don't have to pass around a reference like we do in Java, we can just create the value and use it as a lookup key.
* They're not entirely unique, per the pigeonhole principle unless the hashed output is at least as large as the input you will have collisions where two keys hash to the same values. But for our purposes here, they're unique.
** Not quite everything, but close enough.
For its own data structures Clojure uses hasheq to create the hash of an object. The behaviour is consistent with =, which means that, for example, the list '(1 2 3) is equal to the vector [1 2 3].
All Clojure data structures implement IHashEq which means they have a hasheq function. If we compare the implementation of hasheq for the PersistentList and APersistentVector we see they both extend ASeq and have the same implementation of the hasheq function, and when when getting to primitive types return a consistent value for the same values using a hashing algorithm called Murmur3.
If you look at the implementation of hasheq for longs we see hashLong is used of the Murmur3 class and we get consistent hash code values:
user=> (clojure.lang.Murmur3/hashLong 123)
823512154
user=> (clojure.lang.Murmur3/hashLong 123)
823512154
Similar for other primitive types.
Note that Java's hashcode function has similar behaviour for two types of ordered lists:
user=> (.hashCode (java.util.ArrayList. [1 2 3]))
30817
user=> (.hashCode (java.util.LinkedList. [1 2 3]))
30817
So an instance of ArrayList and LinkedList have the same hashcode as long as they have the same contents.
But a standard Java array returns different hashcodes not based on its contents, but specific to the instance:
user=> (.hashCode (to-array [1 2 3]))
1736458419
user=> (.hashCode (to-array [1 2 3]))
739210872
so two instances of similar arrays are not equal:
user=> (= (to-array [1 2 3]) (to-array [1 2 3]))
false
Now, why is this relevant when using Clojure data structures as keys in a map?
If we create a map with a vector or list as the key, we can look up this value:
user=> (def m {[1 2 3] :foo})
#'user/m
user=> (get m [1 2 3])
:foo
user=> (m [1 2 3])
:foo
also when using another data structure that is equal (=):
user=> (m '(1 2 3))
:foo
This is not possible with Java arrays that have an implementation for their hash codes that is based on the instance, not on the content:
user=> (def m {(to-array [1 2 3]) :foo})
#'user/m
user=> (m (to-array [1 2 3]))
nil
When using Clojure most things are coded using its data structures and it's advantageous that the lookups work based on the content of the data structure ((get-in {[1 2] {#{2 3} :foo}} ['(1 2) #{3 2}]) ;; => :foo).
Input
(def my-cat "meaw")
(def my-dog "baw")
(def my-pets {my-cat "Luna"
my-dog "Lucky"})
Output
(get my-pets my-cat) ;=> "Luna"
(:key my-pets my-cat) ;=> "meaw"
(get my-pets "baw") ;=> "Lucky"
(get my-pets "meaw") ;=> "Luna"
I was looking at ways to reverse a collection using Clojure without using the reverse function and stumbled upon this solution.
(reduce conj '() [1 2 3 4 5]) => (5 4 3 2 1)
I have read the Clojure api with regard to how reduce works but am still baffled as to how it is working in this instance.
Also I have found if I were to pass a vector as the third argument instead of a list ie:
(reduce conj [] [1 2 3 4 5]) => [1 2 3 4 5]
I seem to get back the same vector.
I was wondering if anybody could give me a brief explanation as to to how reduce is working in both instances.
Also I have found this method also reverses a vector:
(into () [1 2 3 4]) => (4 3 2 1) ; ???
The doc string says: conj[oin]. Returns a new collection with the xs 'added'. (conj nil item) returns (item). The 'addition' may happen at different 'places' depending on the concrete type.
For a vector, the natural place to add is the end. For a list, the natural place to add is the front (as with 'cons').
Clojure assoc applied to vector seems have inconsistent behaviour
When index is present in vector, assoc replace the value
(assoc [1 2 3 4 5] 3 42) => [1 2 3 42 5]
When index is next to last one, the vector grows (conj equivalent)
(assoc [1 2 3 4 5] 5 42) => [1 2 3 4 5 42])
Otherwise IndexOutOfBoundsExcpetion is thrown
though it useful in some cases like reduce assoc, this may lead to subtle bugs in a program
Is it expected behaviour or probably bug in assoc for vector?
It is expected. See the docstring for assoc, especially the last note regarding the index argument.
This is described at the top of p. 101 of Clojure Programming.
I am having an issue that can be reduced to the following problem: When the result of a query is one value, sel / $ returns a number, when it is more than one value, it is a sequence:
(with-data (to-dataset [[1 2] [3 4]])
($ :col-1))
yields (2 4), but
(with-data (to-dataset [[1 2]])
($ :col-1))
yields 2.
I would like it to be a sequence at all times, since I want to e. g. apply + to the sequence. I want to avoid checking for the type using (seq?). Any ideas? Is this behaviour of Incanter reasonable?
This is my workaround:
(let [seq-it (fn [a] (if (seq? a) a (list a)))]
(with-data (to-dataset [[1 2]])
(->> ($ :col-1)
(seq-it))))
which yields (2).
I believe this is a bug in Incanter (or you might regard it as a serious design flaw that should be fixed).
It is probably related to the issue discussed here, where 1x1 matrix results get converted to doubles:
https://groups.google.com/forum/?fromgroups=#!topic/incanter/89RNomNMBWA
Does clojure have a powerful 'loop' like common lisp.
for example:
get two elements from a sequence each time
Common Lisp:
(loop for (a b) on '(1 2 3 4) by #'cddr collect (cons a b))
how to do this in Clojure?
By leveraging for and some destructuring you can achieve your specific example:
(for [[a b] (partition 2 [1 2 3 4])](use-a-and-b a b))
There is cl-loop, which is a LOOP workalike, and there are also clj-iter and clj-iterate, which are both based on the iterate looping construct for Common Lisp.
Clojure's multi-purpose looping construct is for. It doesn't have as many features as CL's loop built into it (especially not the side-effecting ones, since Clojure encourages functional purity), so many operations that you might otherwise do simply with loop itself are accomplished "around" for. For example, to sum the elements generated by for, you would put an apply + in front of it; to walk elements pairwise, you would (as sw1nn shows) use partition 2 on the input sequence fed into for.
I would do this with loop, recur and destructuring.
For example, if I wanted to group every two values together:
(loop [[a b & rest] [1 2 3 4 5 6]
result []]
(if (empty? rest)
(conj result [a b])
(recur rest (conj result [a b]))))
Ends up with a result of:
=> [[1 2] [3 4] [5 6]]
a and b are the first and second elements of the sequence respectively, and then rest is what is left over. We can then recur-sively go around until there is nothing left over in rest and we are done.