请在 2024 Clojure 状况调查! 中分享您的想法。

欢迎!请参阅 关于页面 了解此网站的一些信息。

0
core.logic

conda 和 condu 的语义特别重视每个子句的头部,但 core.logic 之上构建的模式匹配宏将主体合并到头部。这意味着在决定选择哪一行时,考虑的是主体位置上的每个表达式,而不仅仅是头部位置的表达式。这是因为整个子句被一个新表达式包裹以绑定模式中出现的隐式指定的 lvars。

以下是示例

`
(matcha ['a]

[['a] u#]
[['a] s#])

;; 展开为

(conda
[(fresh [] (== 'a 'a) u#)]
[(fresh [] (== 'a 'a) s#)])

;; 与以下内容意义不同

(conda
[(== 'a 'a) u#]
[(== 'a 'a) s#])

`

理想情况下,我们可以设计一个新系统,将 conda 的语义与模式匹配相结合。至少,我认为应该在有问题的宏的文档字符串中包含一条警告,指出这种语义差异。

我怀疑这也会使“第三条戒律”警告适用于整个行,而不是仅限于头部/问题,但我尚未调查这个问题。

以下是一个演示意义差异的示例

`
;; 这不成功,因为我们承诺了第一行,
;; 因为疑问成功,但在主体中失败。

(run* [q]
(conda
[(== 'a 'a) u#]
[(== 'a 'a) s#]))

;; => ()

;; 这成功,因为整个行用于确定提交哪一行,
;; 而不是只是头部的问题模式匹配子句。所以当第一行失败时,
;; 将尝试第二行。

(run* [q]
(matcha ['a]
[['a] u#]
[['a] s#]))

;; => (_0)
`

4 个答案

0

评论者:austinhaas

仅供参考

{quote}

第三条戒律

如果在确定 conda(或 condu)行的疑问之前一个变量是新鲜的,那么它在该行的疑问中必须保持新鲜。
{quote}

摘自《合理的方案员》。

0

评论者:dnolen

捕捉得很好,我需要考虑一下这个问题。

0

评论者:dnolen

问题是,我们依赖于不十分灵活的《conde》宏。我们可能需要做一步较低的调整,将每个 Sencond 行包裹在《let》中以构造逻辑变量,然后确保所有头部统一都被包裹在《fresh》中以保持 conde/u 的语义。

0
参考: https://clojure.atlassian.net/browse/LOGIC-129 (由 austinhaas 报告)
...