This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-12-12
Channels
- # adventofcode (49)
- # announcements (22)
- # beginners (33)
- # calva (5)
- # clj-kondo (6)
- # clojure (30)
- # clojure-europe (6)
- # clojure-japan (1)
- # clojure-nl (9)
- # core-logic (17)
- # data-oriented-programming (1)
- # datalevin (1)
- # datomic (2)
- # gratitude (2)
- # jobs (2)
- # kaocha (8)
- # lsp (1)
- # malli (8)
- # meander (8)
- # off-topic (18)
- # rdf (1)
- # re-frame (4)
- # reagent (16)
- # releases (1)
- # sci (1)
- # sql (1)
- # tools-deps (4)
- # xtdb (3)
I'm looking for core.logic guides with real life examples (eg, math questions), does anyone know something that could help?
I'd probably start here https://www.youtube.com/watch?v=iCuVTGWNU3s
Is there a difference between (let [x (lvar)] goals...
and (fresh [x] goals...)
, when no x has been introduced in the run*
expression before?
Yes, there is a difference. Fresh is a goal constructor (I.e. returns a function that takes a substitution/state and returns a stream of answers). A let form is not a goal constructor by itself. You would have to wrap the goals in a conjunction goal. In other words, it's close but not identical. I'm not close to the source at the moment, but you can macro expand fresh and see what's underneath. In microkanren, which is not core.logic, fresh basically maps to a call to a lambda where the parameter is a newly created lvar and the function is a goal constructor that returns a goal that is a conjunction of the goals in the fresh. I highly encourage you to read through the microkanren paper (see the papers section of http://minikanren.org. It's less than a page of source for the whole implementation and it will really help you understand what's happening under the hood.
Why doesn't this output [:c :f]
?
(do
(db-rel signal input output)
(db
[signal [:a :b :c :e :f] 0]
[signal [:c :f] 1]
[signal [:a :c :d :e :g] 2]
[signal [:a :c :d :f :g] 3]
[signal [:b :c :d :f] 4]
[signal [:a :b :d :f :g] 5]
[signal [:a :b :d :e :f :g] 6]
[signal [:a :c :f] 7]
[signal [:a :b :c :d :e :f :g] 8]
[signal [:a :b :c :d :f :g] 9])
(run* [q]
(fresh [a b]
(signal [a b] 1)
(== q [a b]))))
Got it, I forgot with-db
Will two lvars defined like this: (lvar :a true)
will be the same?
The REPL is your friend:
clojure.core.logic> (identical? (lvar :a true) (lvar :a true))
false
clojure.core.logic> (= (lvar :a true) (lvar :a true))
false
So, no. They are not the same and won’t compare as the same. You can see this in the printed representation:
clojure.core.logic> (lvar :a true)
<lvar::a__4588>
clojure.core.logic> (lvar :a true)
<lvar::a__4591>
If you look at the source, around line 714 you can see most of the creation paths use a unique counter to instantiate the lvar. You can force them to compare as equal using the false
flag:
clojure.core.logic> (= (lvar :a false) (lvar :a false))
true
clojure.core.logic> (lvar :a false)
<lvar::a>
clojure.core.logic> (lvar :a false)
<lvar::a>
I see, very helpful thank you.
Is it safe to assume that run*
returning '()
means a contradiction in the goals?
Okay, thank you
I'm getting a stack overflow error with run*
:
(StackOverflowError) at clojure.core.logic.Substitutions/walk (logic.clj:359)
Does that mean my constraint set is too broad?Oh nevermind, sets aren't supported.