看完之后 富人希基的采访协议 在Clojure 1.2中,对Clojure了解很少,我对Clojure协议有一些疑问:

  • 他们打算做与 结构类型 在Scala?协议对结构类型有什么好处(性能,灵活性,代码清晰度等)?它们是通过反思实施的吗?
  • 关于与Scala互操作性的问题:可以使用协议代替Scala中的结构类型吗?可以在Scala中扩展它们(如果可以应用于协议,将它们应用于协议)?
有帮助吗?

解决方案

完全无关。

Scala是一种静态打字的语言。 Clojure是一种动态类型的语言。这种差异从根本上塑造了两者。

结构类型是静态类型,时期。它们只是使编译器在静态上证明对象具有特定结构的一种方式(我说在这里证明,但是铸造会一如既往地引起虚假的证明)。

Clojure中的协议是创建比反射快得多或在地图中查找事物快得多的动态调度的方法。从语义上讲,它们并没有真正扩展过Clojure的功能,但是在操作上,它们的速度明显比以前使用的机制要快得多。

与Java接口一样,Scala性状与协议更接近协议,但是同样存在静态与动态问题。 Scala性状必须在编译时与类相似,类似于Java接口。即使是第三方,也可以在事实之后的运行时将Clojure协议添加到数据类型中。

通过包装器/代理模式或动态代理等机制,Java和Scala中可以使用诸如Clojure协议之类的东西( http://download.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html )。但是,这将比Clojure协议更笨拙,并且正确获得对象身份也很棘手。

其他提示

Clojure方案的目的是以有效的方式解决表达问题。

看: 简单说明Clojure协议.]

Scala对表达问题的解决方案是隐含的。因此,在语义上, 是与Scala中的Clojure协议最接近的。 (在Haskell中,它将是类型或类型的家庭。)

正如我从中了解的那样 入门博客文章, ,闭合协议更接近Scala特征,而不是结构类型(因此,不能用作其替代品,回答我的第二个问题):

/* ----------------------- */
/* --- Protocol definition */
/* ----------------------- */

(defprotocol Fly
  "A simple protocol for flying"
  (fly [this] "Method to fly"))

/* --- In Scala */    
trait Fly{
    def fly: String
}

/* --------------------------- */
/* --- Protocol implementation */
/* --------------------------- */

(defrecord Bird [nom species]
  Fly
  (fly [this] (str (:nom this) " flies..."))

/* --- In Scala */    
case class Bird(nom: String, species: String) extends Fly{
    def fly = "%s flies..." format(nom)
}

/* --------------------- */
/* --- Dynamic extension */
/* --------------------- */

(defprotocol Walk
  "A simple protocol to make birds walk"
  (walk [this] "Birds want to walk too!"))

(extend-type Bird
  Walk
  (walk [this] (str (:nom this) " walks too..."))

/* --- In Scala */    
trait Walk{
    def walk = "Birds want to walk too!"
}

implicit def WalkingBird(bird: Bird) = new Walk{
    override def walk = "%s walks too..." format(bird.nom)
}

/* --------------- */
/* --- Reification */
/* --------------- */

(def pig (reify
                Fly (fly [_] "Swine flu...")
                Walk (walk [_] "Pig-man walking...")))

/* --- In Scala */    
object pig extends Fly with Walk{
    def fly = "Swine flu..."
    override def walk = "Pig-man walking..."
}

其他答案更好地讲述了问题的其他部分,但是:

它们是通过反思实施的吗?

否 - 协议已编译为JVM接口。实现协议(Reify,除法等)的事物已编译为实现协议接口的JVM类,因此对协议函数的调用与引擎盖下的标准JVM方法调用相同。

实际上,这是协议的动机之一 - 出于速度原因,许多Clojure的内部数据结构都是用Java编写的,因为没有办法在Pure Clojure中进行全速多态性调度。协议提供了这一点。 Clojure在其源代码中仍然有很多Java,但现在可以在Clojure中重写,而不会丧失性能。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top