最近看过Clojure Protocols的演示文稿,我对现有类型的干净方式扩展印象非常深刻,可以通过这种方式完成 . 但是,我很确定已经在其他语言中看到了类似的方法,经过一段时间我发现它是Groovy Categories .
比较一下:
@Category(String) class StringCategory {
String lower() {
return this.toLowerCase()
}
}
use (StringCategory) {
println("TeSt".lower())
assert "test" == "TeSt".lower()
}
相当于Clojure协议(摘自mikera's answer below and tested in ideone.com)
(defprotocol Lowerable
(lower [x]))
(extend-protocol Lowerable
String
(lower [s]
(.toLowerCase s)))
(println (lower "HELLO"))
我的问题是:
-
除了性能差异(据说Clojure在这方面得到了高度优化) - 两种方法之间是否存在语义差异?
-
除了笨拙的语法之外,Groovy方法有什么逻辑错误吗?
免责声明:我是一个完整的Clojure新手!
2 回答
这是使用协议的粗略等效Clojure代码:
关于Clojure协议的关键区别(我认为它与Groovy类别版本不同)
Clojure协议定义不包含任何实现(在这方面它更像是一个接口) . 实现是单独提供的:您可以将Lowerable协议扩展到任意多个不同的类,而无需对类本身或协议定义进行任何更改 . 例如,您可以定义
lower
以处理Rope .上面的Groovy类别专门用于字符串 - 这与Clojure协议不同 . 在这个例子中,定义了Clojure协议"Lowerable",但没有说明有关参数类型的任何内容 .
lower
是一个合适的头等功能 . 因此,您可以使用它来构建更高阶的抽象(通过更高阶函数),这反过来将接受可扩展协议已被扩展的任何参数 .Clojure协议经过大量优化,因为它们旨在利用JVM的快速方法分派 . 因此,它们被编译成非常有效的代码(不需要动态对象检查或反射)
Clojure协议实际上是一个相当独特的solution to the Expression Problem(链接视频非常有趣) . 我认为在另一种语言中与Clojure协议最接近的等价物实际上是Haskell类型 . 即便如此,由于Haskell是静态类型的,并且Clojure是动态类型的,所以它有点延伸....
他所指的Clojure功能如下:
可以随时为任何类型添加实现 - 我写的两个实现都不需要以任何方式进行协作 .
但是,我不太了解Groovy对这个问题本身做出任何实质性的评论;我只能帮助描述问题的Clojure方面 .