Fork me on GitHub
#core-logic
<
2015-08-23
>
nblumoe06:08:41

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):

nblumoe06:08:45

(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

nblumoe06:08:01

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?

nblumoe11:08:01

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

nberger11:08:11

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

nblumoe15:08:55

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:

nblumoe15:08:06

(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)))
; => ()

nblumoe15:08:23

Is that expected?? <!channel>

bhagany15:08:09

@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.

bhagany15:08:55

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

nblumoe15:08:22

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")))

nblumoe15:08:55

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? 😄

bhagany16:08:57

@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 :)

bhagany16:08:35

I just hang out here hoping to absorb useful things

nberger16:08:33

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

nberger16:08:08

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

nberger16:08:42

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

nberger16:08:39

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 :)

nberger16:08:22

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

nblumoe17:08:56

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