10

Clojure1.2のプロトコルに関するRichHickeyのインタビューを見て、 Clojureについてほとんど知らなかった後、Clojureプロトコルについていくつか質問があります。

  • それらはScalaの構造型と同じことをすることを意図していますか?プロトコルは構造タイプ(パフォーマンス、柔軟性、コードの明確さなど)に対してどのような利点がありますか?それらはリフレクションを通じて実装されていますか?
  • Scalaとの相互運用性に関する質問:Scalaの構造型の代わりにプロトコルを使用できますか?それらをScalaで拡張できますか(「拡張」用語をプロトコルに適用できる場合)?
4

4 に答える 4

15

まったく無関係。

Scala は静的に型付けされた言語です。Clojure は動的型付け言語です。この違いは、基本的に両方を形成します。

構造型は静的型、期間です。それらは、オブジェクトが特定の構造を持つことをコンパイラーに静的に証明させる方法にすぎません (ここで証明すると言いますが、キャストはいつものように偽の証明を引き起こす可能性があります)。

Clojure のプロトコルは、リフレクションやマップでの検索よりもはるかに高速な動的ディスパッチを作成する方法です。セマンティックな意味では、これらは Clojure の機能を実際に拡張するものではありませんが、操作的には、以前に使用されていたメカニズムよりも大幅に高速です。

Scala トレイトは、Java インターフェイスと同様にプロトコルに少し近いですが、やはり静的と動的の問題があります。Scala トレイトは、Java インターフェイスと同様に、コンパイル時にクラスに関連付ける必要があります。Clojure プロトコルは、サード パーティによってであっても実行後にデータ型に追加される可能性があります。

ラッパー/プロキシ パターンや動的プロキシ ( http://download.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html )などのメカニズムを介して、Clojure プロトコルのようなものが Java や Scala で可能です。しかし、これらは Clojure プロトコルよりもかなり扱いにくく、オブジェクト ID を正しく取得するのも難しいものです。

于 2010-12-22T15:48:47.560 に答える
10

Clojure のプロトコルの目的は、式の問題を効率的に解決することです。

[参照: clojure プロトコルの簡単な説明. ]

Expression Problem に対する Scala のソリューションは Implicits です。したがって、意味的に、これは Scala の Clojure プロトコルに最も近いものです。(Haskell では、Typeclasses または Type Families になります。)

于 2010-12-22T20:52:28.747 に答える
6

この紹介ブログ投稿から理解したように、クロージャー プロトコルは構造型ではなく、Scala トレイトに近いものです (したがって、2 番目の質問に答えて、それらの代わりとして使用することはできません)。

/* ----------------------- */
/* --- 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..."
}
于 2010-12-22T14:29:17.537 に答える
4

他の回答は、質問の他の部分をよりよく物語っていますが、次のとおりです。

それらはリフレクションを通じて実装されていますか?

いいえ - プロトコルは JVM インターフェースにコンパイルされます。プロトコルを実装するもの (reify、defrecord など) は、プロトコル インターフェイスを実装する JVM クラスにコンパイルされるため、プロトコル関数の呼び出しは、内部では標準の JVM メソッド呼び出しと同じです。

これは、実際にはプロトコルの動機の 1 つでした。Clojure の内部データ構造の多くは、速度上の理由から Java で記述されていました。純粋な Clojure では、フルスピードのポリモーフィック ディスパッチを行う方法がなかったためです。プロトコルはそれを提供します。Clojure のソース コードにはまだ多くの Java が含まれていますが、パフォーマンスを損なうことなく Clojure ですべてを書き直すことができます。

于 2010-12-22T16:05:23.347 に答える