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*在模式中展开宏,因此它不会将例如 (breed :golden-retriever) 视为引入一个名为 "breed" 的新LVar。还提供了测试。

10 个答案

0

评论者:dnolen

我对我之前没这么做感到惊讶。我们在模式中统一表达式已经有所支持。查看master分支中tests.clj的第1230行。

所以,按我所能理解的那样,这应该正常工作,无需显式支持宏。如果不起作用,则存在一个错误。

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
  在 logic.clj:828


使用函数而不是宏会产生相同的结果


异常在“main”线程中 java.lang.ClassCastException:clojure.core.logic.LVar不能转换为 clojure.lang.IFn
  在 core.clj:67
  在 logic.clj:211
  在 core.clj:65
  在 logic.clj:1160
  在 logic.clj:826
  在 logic.clj:1160
  在 logic.clj:823
  在 logic.clj:823
  在 logic.clj:823
  在 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])


并且作为一个函数

(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) ...)形式,这正是我不希望在这种情况下看到的东西。

我不太确定为什么这在这里不起作用,而在matche测试案例中工作。

0

评论者:dnolen

[(type-enum :dragon)]

这个模式似乎说明你想要匹配

[[:type :dragon]]

这里多了一层括号。这是否就是问题所在?

即便如此,我同意展开看起来并不完全正确。我们绝对不应该以那种方式进入序列形式。

0

评论者:joeosborn

是的,这就是在这个案例中的期望结果——一个标签值。这是我天真理解的结果。为什么它在这个案例中失败,而type-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)提供一些便利,所以我想要区分参数的“键部分”(key part)和“值部分”(value part)。对于没有“值部分”的事实看起来有点傻,但它让我能够编写类似于以下这样的过程和函数


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

0
参考:[在这里点击](https://clojure.atlassian.net/browse/LOGIC-44)(由 alex+import 报告)
...