2024 Clojure 状态调查! 中分享你的想法。

欢迎!请在 关于 页面上查看有关如何使用本功能的更多信息。

0
core.logic

目前我找不到一种方法来启用自定义数据类型,以便在两个方向上与顺序对象进行统一。您可以使用 IUnifyTerms 在一个方向上使其工作,但不可能使其在另一个方向上工作(即当顺序对象首先存在时)。

问题似乎出在以下代码中

`
(defn unify-with-sequential* [u v s]
(cond

(sequential? v)
(if (and (counted? u) (counted? v)
      (not= (count u) (count v)))
  nil
  (loop [u u v v s s]
    (if (seq u)
      (if (seq v)
        (if-let [s (unify s (first u) (first v))]
          (recur (next u) (next v) s)
          nil)
        nil)
      (if (seq v) nil s))))

(lcons? v) (unify-terms v u s)
:else nil))

`

如果最终的 nil 可以替换为对一个协议的调用(IUnifyTermsReversed ???IUnifyWithSequential ???),那么我相信这将使它可扩展。

9 答案

0

由 dnolen 发表的评论:

我觉得您不希望您的数据类型实现 ISequential?

0

由 mikera 发表的评论:

这不可取,因为一个表达式也可以是一个叶节点

(+ 3 X) ;; OK 作为顺序
7 ;; 绝对不是顺序!

因此,使 Expression 实现 ISequential 会有问题,并会破坏各种契约......

尝试将叶节点与顺序对象进行统一应该失败,但这是我需要自行实现的逻辑(我认为是)。

0

由 dnolen 发表的评论:

我还是不理解,因为我缺少一些关于您用例的上下文。您有一个具体的 core.logic 示例,您认为应该可以工作吗?

0
by

由 mikera 发表的评论:

当然,这里是我的测试用例

(let [ex1 (ex [+ 1 X])] ;; 包含 (+ 1 X) 的表达式 (is (= [(ex X)] (run* [q] (fresh [op p] (== [op p q] ex1))))) ;; 失败 (is (= [(ex X)] (run* [q] (fresh [op p] (== ex1 [op p q]))))) ;; 成功 )

第一种情况失败了(因为 unify-with-sequential* 返回 nil)。第二种情况没问题,因为它是通过我自己的 IUnifyTerms 实现完成的。我可能错了,但我认为没有在 core.logic 内部进行更改,我是无法使其工作的。

0
by

由 dnolen 发表的评论:

我们以前支持双向统一,但这导致了大量的协议需要实现。最近我一直想,提供强制转换协议,比如 ICoerceToSequential,可能是有用的。

0
by

由 mikera 发表的评论:

我认为如果自定义数据结构将成为 core.logic 的第一类公民,那么支持双向统一可能是必要的。

我明白您可以用 ICoerceToSequential 来实现这一点,所以这可能是一个好的解决方案。我们在 core.matrix 中做了一些类似的事情(以处理不同后端矩阵实现之间的强制转换)。

0
by

由 dnolen 发表的评论:

自定义数据结构已经是第一类了。是否应该允许使用核心 Clojure 接口/协议/类型来过度加载自定义类型的统一,完全是另一回事。

我很抱歉造成混淆。我不清楚您为什么想让序列工作,从您的示例中看,您似乎有合适表达式类型,为什么您需要与序列进行统一有什么优势呢?

0
by

由 mikera 发表的评论:

如果您有“类似序列”的数据结构,这些结构不严格按顺序排列,但从概念上讲是等价的序列,这可能很重要。我的自定义表达式类型就是一个例子,从互操作性的角度来看,java.util.ArrayList 这样的东西也值得考虑。

碰巧的是,我暂时改回了使用常规列表,所以这对我来说不是一个问题。但这可能仍然值得思考。

进行这种统一的好处有几个:
a) 标记法 - 可以使用常规的 Clojure 列表和向量进行统一,以便与类似序列的东西相结合
b) 效率 - 当不需要时避免构造新的自定义对象(尽管在大多数情况下,成本可能过于微不足道,无需关心……)

当然,您可能会认为避免这些复杂的东西更为简单和纯粹,这当然是可以的。但似乎很遗憾,有了所有这些可扩展的协议,却无法完全扩展到自定义类型的功能……

0
参考:[https://clojure.atlassian.net/browse/LOGIC-123](https://clojure.atlassian.net/browse/LOGIC-123)(由 mikera 汇报)
...