2024年Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面以获取更多关于如何使用本站的信息。

0 投票
core.logic

因此,标记的数据结构在关系型数据库中可能很有趣。比如说,你有一个带有关于狗的默认逻辑的数据库关系。

`
(defna friendlyo [Dog-Or-Breed]

([:Spot] succeed)
([:Spike] fail)
([Other-Dog] (fresh [Breed] (dog-breed Other-Dog Breed) (friendlyo Breed)))
([(breed :miniature-dachshund)] fail)
([(breed :golden-retriever)] succeed)
;. . .)

`

假设有一个宏(defmacro breed (link: t) `(link: :breed ~t))。

这比将等 explicitly放入其中更好,因为它可以在编译时进行检查,更不容易出错,减少了重复等。

这个小补丁使得ex*可以在模式中展开宏,因此它不会将例如)作为 "breed" 的引入。还有一个测试。

10 个回答

0 投票

评论者:dnolen

我很惊讶这还没有实现。我们已经在模式中统一参数表达有了支持。查看master分支中的tests.clj的第1230行。

所以这应该会正常工作,据我所知,无需显式支持宏。如果不起作用,那么就是有bug。

0 投票
_评论者:joeosborn_

至少在0.7.5版本中,匹配宏会抛出一个运行时错误


异常线程"main" java.lang.ClassCastException: clojure.core.logic.LVar 不能转换成 clojure.lang.IFn
    在 core.clj:61
    在 logic.clj:211
    在 core.clj:58
    在 logic.clj:1160
    在 logic.clj:1160
    在 logic.clj:823
    在 clojure.core.logic$fn__890$fn__891.invoke(logic.clj:828) 中


使用 fn 而不是宏可以得到相同的结果


异常线程"main" java.lang.ClassCastException: clojure.core.logic.LVar 不能转换成 clojure.lang.IFn
    在 rl.core$drawable_$fn__235$fn__248$fn__249$_inc__250$fn__251.invoke(core.clj:67) 中
    在 logic.clj:211
    在 rl.core$drawable_$fn__235$fn__248$fn__249$_inc__250.invoke(core.clj:65) 中
    在 logic.clj:1160
    在 clojure.core.logic$fn__894$_inc__895.invoke(logic.clj:826) 中
    在 logic.clj:1160
    在 logic.clj:823
    在 logic.clj:823
    在 logic.clj:823
    在 clojure.core.logic$fn__890$fn__891.invoke(logic.clj:828) 中


以下是对(glyph-)的引用(不要在意多余的 [],由于在时间数据库中维持事实标识的便利性,我有一个奇怪的键/值问题)

(defna glyph- [Key Val]
    ([[Thing] [Glyph]] (thing- [Thing]) (on-fire_ *turn* [Thing]) (== Glyph \δ))
    ([[Thing] [Glyph]] (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (glyph- [Type] [Glyph])))
    ([[(type-enum :player)] [Glyph]] (== Glyph \@))
    ([[(type-enum :dragon)] [Glyph]] (== Glyph \D))
    ([[Type] [Glyph]] (== Glyph \?)))


和 type-enum 作为宏

(defmacro type-enum [v] `[:enum :type ~v])


以及作为 fn

(defn type-enum [v] [:enum :type ~v])


我会尝试看看我的示例在 HEAD 中是否有效。
0 投票

评论者:joeosborn

在 HEAD 中的这个测试案例中也有同样的异常(对不起,因为所有的数据)

`
(defrel thing- [Thing])
(defrel type- [Thing] [Type])
(fact thing- [0])
(fact thing- [1])
(fact thing- [2])
(fact type- [0] [:player])
(fact type- [1] [:dragon])
(fact type- [2] [:pig])
(defn type-enum [t] [:type t])
(defna drawable- [Key]
([[Thing]] (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (drawable- [Type])))
([[(type-enum :player)]] succeed)
([[(type-enum :dragon)]] succeed))

(deftest do-fns-work

(is (= (run* [q] (drawable- [q])) '(0 1))))

`

现在看来,我可能期望返回值格式错误,但重点是甚至没有走那么远。

使用 REPL,我检查了 (defna drawable- . . .) 的展开(稍微整理了一下)

`
(def drawable- (clojure.core/fn ([Key]
(clojure.core.logic/conda

  ((clojure.core.logic/fresh [Thing] (clojure.core.logic/== [Thing] Key) (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) (drawable- [Type])))) 
	((clojure.core.logic/fresh [type-enum] 
	  (clojure.core.logic/== [(type-enum :player)] Key) succeed))
	((clojure.core.logic/fresh [type-enum] 
	  (clojure.core.logic/== [(type-enum :dragon)] Key) succeed))))))

`

注意 (clojure.core.logic/fresh (link: type-enum) . . .) 形式,这正是我不希望在这个情况下看到的。

我实在不知道为什么这里不工作,而匹配测试案例中却工作了。

0 投票

评论者:dnolen

[(type-enum :dragon)]

这个模式看起来像你想要匹配

[[:type :dragon]]

这里有额外的括号级数。这是否是情况?

即便如此,我同意展开看起来不太对。我们绝对不应该进入这样的 seq 形式。

0 投票

评论者:joeosborn

是的,这正是本例中期望的结果——在我的简单理解中是一个标记的值。为什么它失败了,而:1230上线测试没有失败,问题是不是因为它生成的是向量而不是列表?将fn改为返回列表而不是向量似乎没有帮助。

就我所知,我的补丁没有表现出这种行为(至少对于宏来说是这样,我还没有用它来测试fn)。

0 投票

评论者:dnolen

我的意思是,你不想有下面这样的吗?

(defna drawable- [Key] ([[Thing]] (thing- [Thing]) (fresh [Type] (type- [Thing] [Type]) ( drawable- [Type])])) ([(type-enum :player)] succeed) ([(type-enum :dragon)] succeed))

请注意,我已经删除了一层方括号。

0 投票
_评论者:joeosborn_

不!我实际上想要两者都有。我正在做一些时态逻辑的工作,我想为“更新”流畅的东西提供一些便利,所以我想区分参数的“键部分”和“值部分”。对于没有“值部分”的事实看起来有点愚蠢,但允许我编写类似这样的过程和fn。


(defrel heldo 时间 流畅)
(defrel ¬heldo 时间 流畅)
(declare fluent-obtainedo) ; 最近一次的 'held' 没有由 '¬held' 终止,或者失败
(defn alter-fluent [时间 关系 键 新值]
  ;todo: 错误检查,确保旧值 != 新值,旧值获得,新值不获得
  (doseq [old-val (run* [old-val] (fluent-obtainedo 时间 [关系 键 old-val]))]
    (fact ¬heldo 时间 [关系 键 old-val]))
  (fact heldo 时间 [关系 键 新值]))
. . .
(fact heldo 0 ['pos [0] [0 0]])
. . .
(alter-fluent 1 'pos [0] [1 1])


我会以这种方式编写所有非时态流畅的东西,以保持一致性并帮助防止错误。
0 投票

评论者:dnolen

我将在周末尝试更仔细地查看这个问题。

0 投票

评论者:dnolen

我们在这里考虑一个更通用的解决方案:[http://github.com/clojure/core.logic/wiki/Better-syntax-support](http://github.com/clojure/core.logic/wiki/Better-syntax-support)

0 投票
参考:[https://clojure.atlassian.net/browse/LOGIC-44](https://clojure.atlassian.net/browse/LOGIC-44)(由 alex+import 报告)
...