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
by

评论者:dnolen

好吧,我需要考虑这个问题。

0
by

评论者:dnolen

问题在于我们依赖于 conde 宏,它不太灵活。我们可能需要再低一级做些事情,以便将每个 conde 行包裹在一个 let 中,以构建逻辑变量,并确保所有头统一都被包裹在一个 fresh 中,从而保留 conda/u 的语义。

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