2012-03-29 9 views
8

最近Clojureプロトコルのプレゼンテーションを見てきましたが、私は既存のタイプへの拡張をこのように行うことができることに非常に感銘を受けました。 しかし、他の言語でこれをやっているのと同じような方法を既に見てきたことは確かであり、しばらくしてGroovyのカテゴリであることが分かりました。ClojureプロトコルとGroovyカテゴリの相違点

この比較:私の質問がある

(defprotocol Lowerable 
    (lower [x])) 

(extend-protocol Lowerable 
    String 
    (lower [s] 
     (.toLowerCase s))) 

(println (lower "HELLO")) 

mikera's answer below and tested in ideone.comから取られた)Clojureのプロトコルと同等に

@Category(String) ​class StringCategory { 
    String lower() { 
    return this.toLowerCase() 
    } 
} 

use (StringCategory) { 
    println("TeSt".lower()) 
    assert "test" == "TeSt".lower() 
} 

を:

  1. パフォーマンスの違いから、ほかに(それはと言われていますこの点に関してClojureは高度に最適化されています) - 2つのアプローチの間には意味的な違いがありますかチェス?
  2. ぎこちない構文のほかに、Groovyのアプローチには論理的に間違っているものはありますか?

免責事項:私は完全なClojure初心者です!

+0

この質問はかなり興味深いものです。私たちのClojure-enlightened以外のClojureの同等物、および構文/簡潔性の比較のためにClojureの同等物を追加できますか? :D – epidemian

+0

申し訳ありませんが、私はしたいと思います、それはできません。サイトhttp://clojure.org/protocolsには非常に似たサンプルがありますが、今は同等のコードをテストすることができないため、動作しないコードを投稿したくありません。残念ながら、GroovyのWebコンソールのようなWebコンソールはありません(try-clojure.orgにはコンソールがありますが、改行で区切ったコードを貼り付けても失敗します)。 – Ice09

+0

[ideone](http://ideone.com/)で試してみることもできますか? – epidemian

答えて

10

ここプロトコルを使用してラフ同等のClojureコードです:

(defprotocol Lowerable 
    (lower [x])) 

(extend-protocol Lowerable 
    String 
    (lower [s] 
     (.toLowerCase s))) 

(lower "HELLO") 
=> "hello" 

(私はGroovyのカテゴリバージョンから、それが独特の作ると信じて)Clojureのプロトコル

  • について注意すべき重要な違いClojureのプロトコルは、定義には実装が含まれていません(この点ではインタフェースに似ています)。実装は個別に提供されています。クラス自体またはプロトコル定義に変更を加えることなく、下位プロトコルを好きなだけ多くの異なるクラスに拡張できます。たとえば、lowerを定義してRopeで作業することができます。
  • 上記のあなたのGroovyカテゴリは文字列に特化しています - これはClojureプロトコルでは当てはまりません。この例では、Clojureプロトコル "Lowerable"は引数のタイプについて何も言わずに定義されています。
  • lowerは、適切なファーストクラスの関数です。したがって、これを使用して高次関数を介して高次の抽象化を構築すると、下位プロトコルが拡張された引数を受け入れることになります。
  • Clojureプロトコルは、JVMの高速メソッドディスパッチを利用するように設計されているため、大幅に最適化されています。従って、それらは

Clojureのプロトコルは実際にかなり独特solution to the Expression Problem(リンクされたビデオはかなり興味深いものです)(必要な動的なオブジェクトの検査や反射がない)非常に効率的なコードにダウンコンパイルします。私は、別の言語のClojureプロトコルに最も近いのは、実際にはHaskell型クラスだと思います。それでも、Haskellは静的に型付けされているので、Clojureは動的に型付けされているので、それはちょっとしたストレッチです。

+0

ありがとう、それは素敵な説明です。実際には、さまざまな実装が実際より強力です。しかし、私は{{Mixing}}、{{Delegate}}と{{Category}}のアプローチを試さなければならないでしょう。私はあなたの解決策(と追加されたprintln)を私の質問をideone-Linkに広げてもらうことを躊躇しません。 – Ice09

5

彼がどのように見えるに言及だClojureの機能:

(defprotocol StringMunging 
    (lower [this])) 

(extend-protocol StringMunging 
    String 
    (lower [this] 
    (.toLowerCase this)) 

    clojure.lang.Keyword 
    (lower [this] 
    (keyword (lower (name this))))) 

user> (lower "TeSt") 
"test" 
user> (lower :TeSt) 
:test 

実装はいつでも任意のタイプのために追加することができます - 私はどのような方法で協力することを書いた2つの実装のための必要はありません。

しかし、私はGroovyを十分に理解していないので、質問自体について実質的なコメントをすることはできません。私は質問のClojure側を説明するのに役立つだけです。

+0

ポイントを示すための素敵な短いedxample。 – Ice09