代码之家  ›  专栏  ›  技术社区  ›  Carcigenicate

为什么ASEQ需要集合来实现序列以允许等价?

  •  5
  • Carcigenicate  · 技术社区  · 6 年前

    我自己写 range 那工具 ISeq . 我的原始实现 equiv 只是打电话 seq 在我的范围和其他列表中,并使用 = :

    (defn equals? [this-range other-range]
      (= (seq this-range) (seq other-range)))
    

    这看起来不错,但后来我遇到了一些奇怪的行为:

    (= (new-range 5 10)
       (range 5 10))
    => true
    
    (= (range 5 10)
       (new-range 5 10))
    => false ; Uh oh
    

    在哪里? new-range 是我的自定义构造函数。

    看看如何 LongRange 处理等价,我检查了它的来源。它代表 ASeq ,和 ASEQ 当量 方法以行开始:

    public boolean equiv(Object obj) {
        if (!(obj instanceof Sequential) && !(obj instanceof List)) {
            return false;
    . . .
    

    因为我的范围没有实现 Sequential List ,此检查失败。它甚至不尝试迭代我的范围来进行值比较。

    这里的理由是什么? 相继的 只是一个空接口。它似乎只是存在于将类“标记”为连续的,而不需要任何方法。

    我只要我的测距仪 相继的 允许检查,但是我想知道我的等价函数是否应该包括与 ASEQ 也。不过,这似乎是一张不必要的支票,因为 顺序 将在错误的参数上失败,通过 clojure.lang.RT/seqFrom .

    目的是什么 相继的 检查,我应该执行吗 相继的 为了安抚这种方法,我也应该用类似的方法做这样的检查吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   amalloy    6 年前

    你想从中得到什么样的回报

    (= [1 2] #{1 2})
    

    或来自

    (= '([1 2]) {1 2})
    

    ?在这两种情况下,这两个集合在您之后是不可区分的 seq 它们(取决于 #{1 2} 反正是散列的)。但它们显然不是相等的集合:地图和集合的行为与列表和向量非常不同。区分每一对的主要事情是其中一对是连续的(打算以连续的方式使用),而另一对不是。这就是这个标签界面的用途。

    所以,是的,在声明顺序对象等于其他对象之前,您应该检查序列:它不能合理地等于任何非序列的对象。

    推荐文章