Clojure core.logic 的简单 Prolog

Posted

技术标签:

【中文标题】Clojure core.logic 的简单 Prolog【英文标题】:Simple Prolog to Clojure core.logic 【发布时间】:2020-05-02 22:09:36 【问题描述】:

我最近一直在玩 Prolog,并开始思考如何表示我想用它完成的一些任务,这主要是关于拥有一个事实数据库并对其进行简单查询,将多个事实连接在一起。

但我想在我正在编写 Clojure 的上下文中使用它。似乎core.logic 应该做我想做的事。

但我天真地发现如何将基本的 Prolog 谓词放入 core.logic 中很困难。

例如,我应该如何在 core.logic 中表示像这样简单的东西:

person(phil).
person(mike).
food(cheese).
food(apple).
likes(phil,apple).
likes(phil,cheese).

还有一个类似的查询

food(F),person(P),likes(P,F)

我能找到的大多数介绍都侧重于逻辑编程,而不是数据表示。

【问题讨论】:

你看过 core.logic 上的tests 吗?更多 tests 如果这是可以接受的,我可以将其作为一个答案,以便其他人可以看到这个问题有一个可接受的答案。 好的,那么使用 db-rel 和 db? 有没有类似 Prolog 的同时定义关系和数据的东西? 糟糕。忘了说我从来没有使用过 Clojure。我正在写一个答案,事实看起来很简单,但是这个查询让我对如何转换为 core.logic 感到困惑,所以我不会发布答案。 还注意到core.logic 是基于minikanren 可能有用的。 【参考方案1】:

正如 Guy Coder 所说,core.logic 下的 PLDB 包正是解决了这类问题:

(db-rel person p)
(db-rel food f)
(db-rel likes p f)

(def facts (db
  [person 'phil]
  [person 'mike]
  [food 'cheese]
  [food 'apple]
  [likes 'phil 'apple]
  [likes 'phil 'cheese]))

(with-db facts (run* [p f] (food f) (person p) (likes p f)))

=> ([phil cheese] [phil apple])    p=phil,f=cheese   or   p=phil,f=apple

【讨论】:

以上是关于Clojure core.logic 的简单 Prolog的主要内容,如果未能解决你的问题,请参考以下文章

为啥会返回这个矛盾的 clojure.core.logic/featurec 结果?

Clojure core.logic 中的阶乘

core.logic lvars 上的算术和 clojure 函数

使用 clojure 的 core.logic / minikanren 查找相似的集合

Core.logic的简明解释

为啥 core.logic 的输出重复给出相同的值?