父/子isa中的最低共同祖先?Clojure中的层次结构

父/子isa中的最低共同祖先?Clojure中的层次结构,clojure,lowest-common-ancestor,Clojure,Lowest Common Ancestor,假设我们有这样的父/子层次结构: (derive ::integer ::decimal) (derive ::positive-integer ::integer) (derive ::long ::integer) 什么是Clojure惯用语来实现在这样的层次结构中找到最低共同祖先的方法?即: (lca ::positive-integer ::long) ; => ::integer 我最初的想法包括使用递归函数遍历每个参数的父类的组合,但我怀疑可能有更好的方法 我的动机是将其用

假设我们有这样的父/子层次结构:

(derive ::integer ::decimal)
(derive ::positive-integer ::integer)
(derive ::long ::integer)
什么是Clojure惯用语来实现在这样的层次结构中找到最低共同祖先的方法?即:

(lca ::positive-integer ::long) ; => ::integer
我最初的想法包括使用递归函数遍历每个参数的
父类的组合,但我怀疑可能有更好的方法


我的动机是将其用作多方法的分派函数,该多方法接受2个参数,并根据参数的类型分派到最适合的实现。

函数
返回一个集合,因此您需要
(需要[clojure.set:as s])

现在写:

(defn lca [h1 h2]
  (let [a1 (into #{} (conj (ancestors h1) h1))
        a2 (into #{} (conj (ancestors h2) h2))
        ac (s/intersection a1 a2)]
    (apply (partial max-key (comp count ancestors)) ac)))
让我们试试看

stack-prj.hierarchy> (derive ::integer ::decimal)
nil
stack-prj.hierarchy> (derive ::positive-integer ::integer)
nil
stack-prj.hierarchy> (derive ::long ::integer)
nil
stack-prj.hierarchy> (lca ::positive-integer ::long)
:stack-prj.hierarchy/integer
其工作原理如下:我使用
祖先
获取每种类型的祖先集。对于这两种类型,我使用
conj
,将类型本身添加到结果集中(因为我认为
(lca::integer::long)
应该返回
integer
而不是
decimal
)。使用set intersection,我将所有公共祖先存储到变量
ac

在普通祖先中,我想知道哪一个祖先最多
(comp count祖先)
是一个函数,它采用一种类型并返回其拥有的祖先数。我将
max key
部分应用于此函数,然后(使用
apply
)将结果函数应用于集合
ac
。结果是祖先数量最多的共同祖先,或者说是最少的共同祖先


(请注意,
lca
如果您传递两种类型而没有任何共同祖先,则会给出一个错误!您应该自己决定如何处理此情况。)

谢谢!虽然
祖先
可能应该包装在
集合
中,以防止
交集
在提供由
conj
创建的列表时抛出错误,但在没有祖先的情况下,将其设置为零。顺便问一句,为什么要将
使用到#{}
而不是
集合
,感谢您向我介绍
max key
!我已经使用Clojure好几年了,但我还没有遇到过这个函数。我习惯于使用
转换为
作为将一种收藏类型转换为另一种收藏类型的go-to函数<代码>设置
在这种情况下同样有效;这不是我的风格。