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

这比在这些地方插入(link: :breed :golden-retriever)或其他类似内容要好,因为它是编译时检查的,减少了错误,减少了重复等。

这个小补丁使ex*可以在模式中扩展宏,因此它不会把e.g.(breed :golden-retriever)视为引入一个名为"breed"的新 LVar。还提供了测试。

10 个答案

0

评论者:dnolen

我感到惊讶,这不是已经可以工作了吗。我们已经在模式统一表达式中有了支持。查看master分支中tests.clj的第1230行。

所以,这似乎应该可以正常工作,在我看来,没有必要显式支持宏。如果它不起作用,那么可能是一个bug。

0
_评论者:joeosborn_

至少在0.7.5版本中,匹配宏会产生运行时错误


异常在主线程 "main" java.lang.ClassCastException: clojure.core.logic.LVar无法转换为clojure.lang.IFn
    at rl.core$glyph_$fn__123$fn__144$fn__165$fn__166$_inc__167$fn__168.invoke(core.clj:61)
    at clojure.core.logic.Substitutions.bind(logic.clj:211)
    at rl.core$glyph_$fn__123$fn__144$fn__165$fn__166$_inc__167.invoke(core.clj:58)
    at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
    at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
    at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
    at clojure.core.logic$fn__890$fn__891.invoke(logic.clj:828)


用fn代替宏会产生相同的结果


异常在主线程 "main" java.lang.ClassCastException: clojure.core.logic.LVar无法转换为clojure.lang.IFn
    at rl.core$drawable_$fn__235$fn__248$fn__249$_inc__250$fn__251.invoke(core.clj:67)
    at clojure.core.logic.Substitutions.bind(logic.clj:211)
    at rl.core$drawable_$fn__235$fn__248$fn__249$_inc__250.invoke(core.clj:65)
    at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
    at clojure.core.logic$fn__894$_inc__895.invoke(logic.clj:826)
    at clojure.core.logic$fn__1056$_inc__1057.invoke(logic.clj:1160)
    at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
    at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
    at clojure.core.logic$fn__898$_inc__899.invoke(logic.clj:823)
    at clojure.core.logic$fn__890$fn__891.invoke(logic.clj:828)


以下是(glyph-)的参考信息(不必在意额外的方括号,由于某些对维护时间数据库中事实身份的便利性,我有一个奇怪的键/值机制)。

(defna glyph- [键 值]
    ([[事物] [符文]] (事物- [事物]) (火灾_ *扭转* [事物]) (== 符文 \δ))
    ([[事物] [符文]] (事物- [事物]) (新鲜 [类型] (类型- [事物] [类型]) (符文- [类型] [符文])))
    ([[(类型-枚举 :玩家)] [符文]] (== 符文 \@))
    ([[(类型-枚举 :龙)] [符文]] (== 符文 \D))
    ([[类型] [符文]] (== 符文 \?)))


type-enum是一个宏

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


以及作为函数

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


我将尝试看看我的示例在HEAD上是否工作。
0
by

评论由:joeosborn发表

在HEAD中,这个测试案例也同样抛出异常(很抱歉所有的事实)

`
(defrel thing- [事物])
(defrel 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- [键])
([[事物]] (事物- [事物]) (新鲜 [类型] (类型- [事物] [类型]) (可绘制- [类型])))
([[(类型-枚举 :玩家)]] succeed)
([[(类型-枚举 :龙)]] succeed))

(deftest do-fns-work)

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

`

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

使用REPL,我检查了(defna drawable- ...)的展开情况(略有整理)

`
(def drawable- (clojure.core/fn ([键]
(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 (链接:类型-枚举) ...)表单,这正是我不希望在这个案例中看到的内容。

我不太清楚为什么这里不工作,而匹配测试案例中却工作。

0
by

评论者:dnolen

[(类型-枚举 :龙)]

此模式似乎表明您想要匹配

[:type :龙]

这里多了一级方括号,这是否是情况?

即使如此,我同意展开看起来并不是很对。我们决不应该下沉到一个这样的序列形式。

0
by

评论由:joeosborn发表

是的,这正是此情况下的预期结果——在我的朴素解释中是一个带有标签的值。它失败的原因是它产生了向量而不是列表,而测试案例:1230没有这种情况?将函数返回值从向量改为列表似乎没有帮助。

我的补丁,顺便一提,没有表现出那种行为(至少对于宏来说,尚未用函数测试过)。

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_

不,我实际上想要两者都有。我正在做一些时间逻辑方面的工作,并希望为“更新”流畅性(fluent)提供一些便利,所以我想要区分参数的“键部分”和“值部分”。对于没有“值部分”的事实看起来很傻,但它让我能够写一些像这样的过程和函数


(defrel heldo Time Fluent)
(defrel ¬heldo Time Fluent)
(declare fluent-obtainedo) ; 最新的 'held' 没有由 '¬held' 终止的 最新 'held',或失败
(defn alter-fluent [Time Rel Key NewVal]
  ;todo: 错误检查,确保旧的不等于新的,旧的获得,新的没有获得
  (doseq [old-val (run* [old-val] (fluent-obtainedo Time [Rel Key old-val]))]
    (fact ¬heldo Time [Rel Key old-val]))
  (fact heldo Time [Rel Key NewVal]))
. . .
(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

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