I'm trying to rewrite the below piece of core.logic
code.
(run* [x y]
(fd/in x (fd/domain 1 2))
(fd/in y (fd/domain 1 2)))
o/p,
([1 1] [2 1] [1 2] [2 2])
I tried the below versions but none of them works,
(run* [x y]
(fresh [dom (fd/domain 1 2)])
(fd/in x dom)
(fd/in y dom)))
;; Error Unsupported binding form: (fd/domain 1 2)
(run* [x y]
(fresh [dom]
(== dom (fd/domain 1 2))
(fd/in x dom)
(fd/in y dom)))
O/P:
([1 1])
(run* [x y]
(let [dom (fd/domain 1 2)]
(fd/in x dom)
(fd/in y dom)))
O/P:
([_0 1] [_0 2])
What's the rationale for the 3 versions that I tried? Any help would be greatly appreciated.
fd/domain
returns a concrete value that can be used with other goals/relations in the fd
namespace — you can define it once and use it inside run*
more than once:
(let [dom (fd/domain 1 2)]
(run* [x y]
(fd/in x dom)
(fd/in y dom)))
=> ([1 1] [2 1] [1 2] [2 2])
What's the rationale for the 3 versions that I tried?
The first refactoring doesn't work because fresh
is being used like let
, but it doesn't work like that; fresh
simply allows you to give names to some fresh logic variables.
The second refactoring doesn't work because the domain value is being bound to a logic variable, and fd/in
wants a concrete domain value as its second argument — not a (fresh) logic variable.
The third refactoring doesn't work (I assume) because let
bindings aren't going to work like that inside the run*
macro, which only wants a sequence of goals in its body.