質問

見た後 リッチヒッキーとのインタビュー の上 プロトコル Clojure 1.2では、Clojureについてほとんど知らないことで、Clojureプロトコルについていくつか質問があります。

  • 彼らは同じことをするつもりですか? 構造タイプ スカラで?プロトコルには、構造タイプ(パフォーマンス、柔軟性、コードの明確さなど)よりもどのような利点がありますか?それらは反省によって実装されていますか?
  • Scalaとの相互運用性に関する質問:Scalaの構造タイプの代わりにプロトコルを使用できますか? SCALAで拡張できますか(「拡張」用語をプロトコルに適用できる場合)?
役に立ちましたか?

解決

まったく無関係です。

Scalaは静的に型付けられた言語です。 Clojureは動的にタイプされた言語です。この違いは、両方とも根本的に形作られます。

構造タイプは静的タイプです。それらは、オブジェクトが特定の構造を持つことを静的に証明する方法に過ぎません(ここで証明しますが、鋳造はいつものように偽の証明を引き起こす可能性があります)。

Clojureのプロトコルは、反射や地図で物事を調べるよりもはるかに高速な動的なディスパッチを作成する方法です。セマンティックな意味では、それらはClojureの機能を実際に拡張していませんが、運用上、以前に使用したメカニズムよりも大幅に高速です。

Scala特性は、Javaインターフェイスと同様にプロトコルに少し近いですが、再び静的と動的な問題があります。 Scala特性は、Javaインターフェイスと同様に、コンパイル時間のクラスに関連付けられている必要があります。 Clojureプロトコルは、第三者でさえ事実の後に実行時にデータ型に追加できます。

ラッパー/プロキシパターンやダイナミックプロキシなどのメカニズムを介して、JavaやScalaではClojureプロトコルのようなものが可能です。 http://download.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html )。しかし、それらはClojureプロトコルよりもはるかに不器用なものであり、オブジェクトのアイデンティティを正しく正しくすることも難しいです。

他のヒント

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

見る: Clojureプロトコルの簡単な説明.]

表現問題に対するScalaの解決策はInflicitsです。だから、意味的に、 それ ScalaのClojureプロトコルに最も近いものです。 (Haskellでは、タイプクラスになるか、ファミリーを入力するかもしれません。)

私がこれから理解したように 入門ブログポスト, 、閉鎖プロトコルは、構造タイプではなく、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..."
}

他の回答はあなたの質問の他の部分にもっとよく話しますが、:

それらは反省によって実装されていますか?

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

それは実際にはプロトコルの動機の1つでした - 純粋なClojureでフルスピードの多型派遣を行う方法がなかったため、スピード上の理由で、多くのClojureの内部データ構造がJavaで書かれていました。プロトコルはそれを提供します。 Clojureにはまだソースコードに多くのJavaがありますが、パフォーマンスを失うことなくClojureで書き直すことができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top