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*可以在模式中扩展宏,所以它不会将(link: breed :golden-retriever)视为引入一个新的LVar名为"breed"。也提供了测试。

10 答案

0投票

评论者:dnolen

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

所以这应该可以正常工作,据我所知,无需明确支持宏。如果它不起作用,那么可能存在一个bug。

0投票
评论者:joeosborn

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


异常在"main"线程中发生:java.lang.ClassCastException: clojure.core.logic.LVar cannot be cast to 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 cannot be cast to 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)
    在 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- [键 值]
    ([事物] [符号] (事物- [事物]) (on-fire_ *turn* [事务]) (== 符号 δ))
    ([事物] [符号] (事物- [事物]) (fresh [类型] (类型- [事物] [类型]) (symbol- [类型] [符号])))
    ([[(类型-枚举 :玩家)] [符号]] (== 符号 @))
    ([[(类型-枚举 :龙)] [符号]] (== 符号 D))
    ([类型] [符号]] (== 符号 ?)))


以及类型-枚举为一个宏

(defmacro 类型-枚举 [v] `[:enum :type ~v])


以及作为一个函数

(defn 类型-枚举 [v] [:enum :type ~v])


我将随意尝试看看我的例子在HEAD中是否可行。
0投票

由: joeosborn 添加评论

HEAD中的这个测试案例同样出现异常(抱歉所有的专著都出问题)

`
(defrel 事物- [事物])
(defrel 类型- [事物] [类型])
(fact 事物- [0])
(fact 事物- [1])
(fact 事物- [2])
(fact 类型- [0] [:玩家])
(fact 类型- [1] [:龙])
(fact 类型- [2] [:猪])
(defn 类型-枚举 [t] [:类型 t])
(defna 可绘制的- [键])
([[事物]] (事物- [事物]) (fresh [类型] (类型- [事物] [类型]) (可绘制的- [类型])))
([[(类型-枚举 :玩家)]] succeed)
([[(类型-枚举 :龙)]] succeed))

(deftest do-fns-work)

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

`

现在我看看它,我可能期望一个错误的格式返回值,但关键是连那个都没达到。

使用REPL,我查看了(defna 可绘制的-)的展开(稍作整理)

`
(def 可绘制的- (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 (链接: 类型-枚举) ...) 形式,这正是在这种情况下我不想看到的。

我实在不确定为什么这里不工作,而在matche测试案例中却工作了。

0投票

评论者:dnolen

[(类型-枚举 :龙)]

这个模式看起来像是你想进行匹配

[[:类型 :龙]]

这里有一个额外的方括号级别。这是否如此?

即便如此,我同意展开看起来并非完全正确。我们绝不应该陷入这样的序列形式。

0投票

由: 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

不是这样的!我实际上都想用。我在做一些时态逻辑的事情,我想为“更新”一个流畅项提供一些便利,所以我想要区分参数的“键部分”和“值部分”。对于没有“值部分”的事实看起来有些愚蠢,但它让我可以编写类似这样的过程和函数


(defrel heldo Time Fluent)
(defrel ¬heldo Time Fluent)
(declare fluent-obtainedo) ; 最近的 '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 报告)
...