unexpected behavior in core.logic conjo goal - clojure

I have hard time understanding the following behavior of the conjo goal in core.logic.
First, everything seems fine.
(l/run* [q]
(l/conjo q 2 3 [1 2 3] )) => ([1])
The goal succeeds when q = [1], since (conj [1] 2 3) == [1 2 3]
When on the otherhand I ask for 2 lvars then I get the following result that I don't understand. I was expecting a = [1] and b = 2.
(l/run* [a b]
(l/conjo a b 3 [1 2 3] )) => (([_0 _1] :- (clojure.core.logic/conjo <lvar:a__25296> _1 3 [1 2 3])))
What does the syntax :- (clojure.core.logic/conjo <lvar:a__25296> mean?
Why do I get unbound lvars for a and b? there is only one possibility for the goal to suceed.
Maybe I need to hint it some more.
(l/run* [a b]
(l/== b 2)
(l/conjo a b 2 [1 2 3])) => ()
That's really strange now. I set b to be explicitly be 2 and then no solution for a exists.
Any clue what I miss here?
Edit
There's a typo in the example above. The last one should really be:
(l/run* [a b]
(l/== b 2)
(l/conjo a b 3 [1 2 3])) => ()

Related

Clojure: how to test if a seq is a "subseq" of another seq

Is there an easy / idiomatic way in Clojure to test whether a given sequence is included within another sequence? Something like:
(subseq? [4 5 6] (range 10)) ;=> true
(subseq? [4 6 5] (range 10)) ;=> false
(subseq? "hound" "greyhound") ;=> true
(where subseq? is a theoretical function that would do what I'm describing)
It seems that there is no such function in the core or other Clojure libraries... assuming that's true, is there a relatively simple way to implement such a function?
(defn subseq? [a b]
(some #{a} (partition (count a) 1 b)))
(defn subseq? [target source]
(pos? (java.util.Collections/indexOfSubList (seq source) (seq target))))
***
DISCLAIMER EDIT
This proposal is not reliable for reasons discussed in comments section.
***
#amalloy 's solution has one flaw - it won't work with infinite lazy sequences. So it will loop forever when you run this:
(subseq? [1 2 3] (cycle [2 3 1]))
I propose this implementation to fix this:
(defn- safe-b
"In case b is a cycle, take only two full cycles -1 of a-count
to prevent infinite loops yet still guarantee finding potential solution."
[b a-count]
(take
(* 2 a-count)
b))
(defn subseq? [a b]
(let [a-count (count a)]
(some #{a} (partition a-count 1 (safe-b b a-count)))))
=> #'user/safe-b
=> #'user/subseq?
(subseq? [1 2 3] (cycle [2 3 1]))
=> [1 2 3]
(subseq? [1 2 3] (cycle [3 2 1]))
=> nil
(subseq? [1 2 3] [2 3])
=> nil
(subseq? [2 3] [1 2 3])
=> [2 3]

Translating the insert fact from Prolog to core.logic

I'm toying around with core.logic and trying to translate some Prolog code and run into an endless recursion for the insert facts (taken from R.A.O'Keefe's "Craft of Prolog"):
insert(L, X, [X|L]).
insert([H|T], X, [H|L]) :-
insert(T,X,L).
This is what I've come up so far (please note that the first two arguments are exchanged to match up with conso parameter list):
(defn insert [x l nl]
(conde
[(conso x l nl)]
[(fresh [h t]
(conso h t l)
(insert x t l)
(conso h l nl))]))
The problem I have is that the last two facts from these midje tests will never return.
The first one works just fine as is expected since this only requires the first conso clause.
(fact "Inserting works"
(run* [q] (insert 1 [2] q)) => '((1 2)))
(run* [q] (insert 1 [2 3] q)) => '((1 2 3)))
(fact "We can retrieve the inserted data"
(run* [q] (insert q [2] '(1 2))) => '(1))
(fact "We can retrieve the list data, too"
(run* [q] (insert 1 q '(1 2))) => '((2))))
I guess I'm overlooking something obvious, but what?
Edit: The facts don't reflect the behavior of the Prolog code correctly. The right behavior is like this:
?- insert([2,3], 1, Q).
Q = [1, 2, 3] ;
Q = [2, 1, 3] ;
Q = [2, 3, 1].
So, the second checkable should actually be
(fact "Inserting works"
(run* [q] (insert 1 [2 3] q)) => '((1 2 3) (2 1 3) (2 3 1)))
The solution is to make the recursive insert clause last:
(defn insert [x l nl]
(conde
[(conso x l nl)]
[(fresh [h t]
(conso h t l)
(conso h l nl)
(insert x t l))]))
The Prolog code can be transcribed almost verbatim as core.logic also supports matching.
(defne inserto [L, X, L*]
([L, X, (X . L)])
([(H . T), X, (H . L)] (inserto T, X, L)))
Note that I've kept the order of the Prolog version, rather than the inverted order of the first two logical variables in your version.
user=> (run* [q] (inserto [2] 1 q))
((1 2))
user=> (run* [q] (inserto [2 3] 1 q))
((1 2 3))
user=> (run* [q] (inserto [2] q [1 2]))
(1)
user=> (run* [q] (inserto q 1 [1 2]))
((2))

clojure core.logic counting elements in a set

I try to do something like this in core.logic
(defn count-different-elements-in-list [coll]
(count (set coll)))
this works with integers just fine
(should= 1 (count-different-elements-in-list '(1 1 1)))
(should= 2 (count-different-elements-in-list '(1 1 2)))
(should= 3 (count-different-elements-in-list '(1 3 2)))
but now I'm trying to use core.logic to solve some stuff and there it get's messy
(run* [a b c]
;;the variables get values between 1 and 3
(fd/in a b c (fd/interval 1 3))
;; in the list there should only be 2 different values
(== 2 (count-different-elements-in-list '(a b c))))
but here comes the problem, a b c don't get passed as values to the function. They get passed as variables. With three variables count-different-elements-in-list returns always 3 and core.logic doesn't find a solution (empty list).
But I'm looking for this result.
([1 1 2] [1 2 1] [2 1 1]
[1 1 3] [1 3 1] [3 1 1]
[2 2 1] [2 1 2] [1 2 2]
[2 2 3] [2 3 2] [3 2 2]
[3 3 1] [3 1 3] [1 3 3]
[3 3 2] [3 2 3] [2 3 3])
You need to core.logic/project logic vars into non-relational goals, like the normal function count-different-elements-in-list. Unfortunately, you cannot project finite domain logic vars, like a, b, and c, that are not constrained to a single value. (See: this question)
In the example you have, you can swap out the fd/in and fd/interval for a generated range and membero. This would remove the unconstrained finite domain vars, keep the range constraint for integers, and allow for projection.
(def interval (vec (range 1 4)))
(run* [a b c]
(membero a interval)
(membero b interval)
(membero c interval)
(project [a b c]
(== 2 (count-different-elements-in-list (list a b c)))))

Puzzled: Clojure for loop with :while -> unexpected behaviour?

I've been learning Clojure and puzzled by the following:
user=> (for [a (range 1 4) b (range 1 4)] [a b])
([1 1] [1 2] [1 3] [2 1] [2 2] [2 3] [3 1] [3 2] [3 3]); _no surprise here_
Let's add :while (not= a b), I expect to see an empty list as the loop should stop if the condition is false. In this case it's the very first item where a=b=1. Let's see:
user=> (for [a (range 1 4) b (range 1 4) :while (not= a b) ] [a b])
([2 1] [3 1] [3 2]) ; _surprise!_
Changing :while to :when to filter out (= a b) pairs
user=> (for [a (range 1 4) b (range 1 4) :when (not= a b) ] [a b])
([1 2] [1 3] [2 1] [2 3] [3 1] [3 2]); _expected_
Could anyone explain why (for [ ... :while ..] ...) behaves like this?
I'm using Clojure 1.3 on OS X.
Thank you and apologize for the lack of formatting. This is my virgin post on StackOverflow.
Let's look at each iteration.
a = 1
b = 1 -> a == b, break because of while
a = 2
b = 1 -> a != b, print [2 1]
b = 2 -> a == b, break because of while
a = 3
b = 1 -> a != b, print [3 1]
b = 2 -> a != b, print [3 2]
b = 3 -> a == b, break because of while
The :while condition in for only terminates the inner-most loop. I use for all the time, but :while so rarely that I never realized this; thanks for the great question!
Sadly I think the best you can do is wrap a take-while around the for, since you want a "global" stop-counter on the output sequence, not a stop-counter on one of the input sequences you're iterating over. For example:
(->> (for [a (range 1 4)
b (range 1 4)]
[a b])
(take-while (fn [[a b]] (not= a b))))
()

Standard version or idiomatic use of (fn [f & args] (apply f args))

Every so often I find myself wanting to apply a collection of functions on several collections of parameters. It's easy to do with map and a very simple function.
(map
(fn invoke [f & args] (apply f args))
[- + *]
[1 2 3]
[1 2 3]
[1 2 3])
(-1 6 27)
Searching the web turns up quite a few libraries that define a similar function, often called funcall or invoke. Because of Clojure's penchant for variadic functions, I cannot help but think there should already be a default version of this function.
Is there, or is there another idiomatic way to solve situations like this ?
Edit:
Another form may be
(map
(comp eval list)
[- + *]
[1 2 3]
[1 2 3]
[1 2 3])
(-1 6 27)
Which scares me because of the eval.
If you really don't have a clue about the function name, but you know what the in- and output have to be, you can try https://github.com/Raynes/findfn.
(find-arg [-1 6 27] map '% [- + *] [1 2 3] [1 2 3] [1 2 3])
;=> (clojure.core/trampoline)
This tells us that
(map trampoline [- + *] [1 2 3] [1 2 3] [1 2 3])
;=> (-1 6 27)
Actually, you can abuse trampoline as funcall in clojure. But it is hardly idiomatic, because it is a Lisp-1. The above code evaluates to:
[(trampoline - 1 1 1), (trampoline + 2 2 2), (trampoline * 3 3 3)] which then becomes
[-1 6 27] (in the form a of lazyseq to be precise).
As Adrian Mouat points out in the comment below, this probably isn't the preferred way to solve it. Using a funcall like construct smells a bit funny. There must be a cleaner solution. Until you've found that one, findfn can be helpful ;-).
Edit: this will do what you want (as #BrandonH mentioned):
(map #(apply %1 %&) [- + *] [1 2 3] [1 2 3] [1 2 3])
But this is hardly an improvement over your version -- it just uses a shorthand for anonymous functions.
My understanding is that FUNCALL is necessary in Common Lisp, as it's a Lisp-2, whereas Clojure is a Lisp-1.
There isn't a funcall or equivalent function in the standard Clojure library that works exactly this way. "apply" is pretty close but needs a collection of arguments at the end rather than being purely variadic.
With this in mind, you can "cheat" with apply to make it work as follows by adding an infinite list of nils to the end (which get considered as empty sequences of additional arguments):
(map apply [- + *] [1 2 3] [1 2 3] [1 2 3] (repeat nil))
=> (-1 6 27)
Overall though, I think the sensible approach if you really want to use this function frequently is just to define it:
(defn funcall [f & ps]
(apply f ps))
(map funcall [- + *] [1 2 3] [1 2 3] [1 2 3])
=> (-1 6 27)
(map #(%1 %2 %3 %4) [- + *][1 2 3][1 2 3][1 2 3])
(-1 6 27)
The problem is that if you want to allow a variable number of arguments, the & syntax puts the values in a vector, necessitating the use of apply. Your solution looks fine to me but as Brandon H points out, you can shorten it to #(apply %1 %&).
As the other answerers have noted, it has nothing to do with funcall which I think is used in other Lisps to avoid ambiguity between symbols and functions (note that I called the function as (%1 ...) here, not (funcall %1 ...).
I personally think your first version is pretty clear and idiomatic.
Here's an alternative you might find interesting to consider however:
(map
apply
[- + *]
(map vector [1 2 3] [1 2 3] [1 2 3]))
=> (-1 6 27)
Note the trick of using (map vector ....) to transpose the sequence of arguments into ([1 1 1] [2 2 2] [3 3 3]) so that they can be used in the apply function.
Another approach which is fairly self explanatory: "for each nth function, apply it to all nth elements of the vectors":
(defn my-juxt [fun-vec & val-vecs]
(for [n (range 0 (count fun-vec))]
(apply (fun-vec n) (map #(nth % n) val-vecs))))
user> (my-juxt [- + *] [1 2 3] [1 2 3] [1 2 3])
(-1 6 27)
I can't right now thing of a clojure.core function that you could plug into your map and have it do what you want. So, I'd say, just use your own version.
Matt is probably right that the reason there isn't a funcall, is that you hardly ever need it in a Lisp-1 (meaning, functions and other bindings share the same name space in clojure)
What about this one? It selects the relevant return values from juxt. Since this is all lazy, it should only calculate the elements needed.
user> (defn my-juxt [fns & colls]
(map-indexed (fn [i e] (e i))
(apply map (apply juxt fns) colls)))
#'user/my-juxt
user> (my-juxt [- + *] [1 2 3] [1 2 3] [1 2 3])
(-1 6 27)