core-logic

nblumoe 2015-08-23T06:53:41.000106Z

Hey, I am dabbling in core.logic. Playing with some naive ideas like the following, which shows some weird behavior (see the indicated return values from the solver):

nblumoe 2015-08-23T06:53:45.000107Z

(defn sub-string? [s sub]
  (boolean (re-find (re-pattern sub) s)))

(sub-string? "123" "3")
;=> true

(sub-string? "123" "4")
;=> false

(l/run* [q]
  (l/membero q (range 200 1000 12))
  (l/== (sub-string? (str q) "9") true))
; randomly (?) returns either () or all the matches from the first logical
; expression, ignoring the second one

nblumoe 2015-08-23T06:57:01.000111Z

I guess I am doing something wrong with using a regular function in the logical expression. but how would I make such a thing work?

nblumoe 2015-08-23T11:17:01.000114Z

The string representation of q is probably not representing it's value. But how to check for q's value then?

nberger 2015-08-23T11:55:11.000116Z

q is an lvar. You could use pred to " Check a predicate against the value logic var."

nblumoe 2015-08-23T15:17:55.000118Z

hm, thanks @nberger. this seemed to be pointing in the right direction. I could not make it work with (str q) but at least with comparing q as an int like #(= % 224). However, I made an odd observation. Why is the result dependent on the order of logical expressions in these two cases:

nblumoe 2015-08-23T15:18:06.000119Z

(l/run* [q]
  (l/project [q] (l/== q 224))
  (l/pred q #(=  % 224))
  (l/membero q (range 200 1000 12)))
; => (224)

(l/run* [q]
  (l/pred q #(=  % 224))
  (l/project [q] (l/== q 224))
  (l/membero q (range 200 1000 12)))
; => ()

nblumoe 2015-08-23T15:18:23.000120Z

Is that expected?? <!channel>

bhagany 2015-08-23T15:35:09.000123Z

@nblumoe: I am a complete noob at this, so this will likely get corrected, but - I think your anonymous function assumes that q is ground. Here, == grounds q before the anonymous function in example 1, but not in example 2.

bhagany 2015-08-23T15:36:55.000124Z

iirc, the order dependence is kind of an implementation detail, but it does leak in cases like this.

nblumoe 2015-08-23T15:45:22.000125Z

cool, thanks @bhagany. was able to get my initial idea working now:

(l/run* [q]
  (l/membero q (range 200 1000 12))
  (l/pred q #(sub-string? (str %) "9")))

nblumoe 2015-08-23T15:46:55.000126Z

Is there some kind of idiomatic way to make this order dependence explicit? Or is it just an issue for me because of my dangerous lack of knowledge about logic programming? 😄

bhagany 2015-08-23T16:07:57.000127Z

@nblumoe: I'm not aware of any idiom ... My instinct is to avoid things that depend on order, but I also haven't really internalized the kind of thinking necessary for logic programs :)

bhagany 2015-08-23T16:08:35.000128Z

I just hang out here hoping to absorb useful things

nberger 2015-08-23T16:48:33.000129Z

Yeah, many things depend on order... There's not much to do about that except knowing the exact semantics of each constraint, which is not trivial if your name isn't David :P

nberger 2015-08-23T16:50:08.000130Z

I now found that predc might be better than pred because it will delay evaluation if the var is not ground, like in the second of your two examples

nberger 2015-08-23T16:50:42.000131Z

Haven't tried it tho because I'm not close to a computer now

nberger 2015-08-23T16:51:25.000132Z

^^^ @nblumoe

nberger 2015-08-23T16:55:39.000133Z

The problem in the second example is that q is not ground yet, so it's an lvar when the predicate is evaluated... And an lvar is never equal to 224. In the first example it was already unified with 224 on the first constraint, so by the time of the second constraint it's grounded to 224, which is course is equal to 224 :)

nberger 2015-08-23T16:57:22.000135Z

Perhaps I just said the same as @bhagany did, but using more words :/

nblumoe 2015-08-23T17:07:56.000136Z

(l/run 3 [q]
  (l/predc q #(boolean (re-find #"9" (str %))))
  (l/membero q (range 200 1000 12)))
; =&gt; (296 392 596)
👍

nberger 2015-08-23T17:31:23.000137Z

Cool :simple_smile: