2012-03-29 93 views
8

最近看到了Clojure協議的演示文稿,對於現有類型的乾淨方式擴展可以這樣完成,我對此印象非常深刻。 但是,我很確定已經看到在其他語言中使用這種方法的類似方式,並且經過一段時間後我發現它是Groovy類別。Clojure協議和Groovy類別之間的區別

比較:

@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")) 

我的問題是:

    從性能差異
  1. 之外(這是說, Clojure在這方面高度優化) - 這兩種方式之間是否存在語義差異? CHES?
  2. 除了笨拙的語法,Groovy方法有什麼邏輯錯誤嗎?

聲明:我是一個完整的Clojure新手!

+0

我覺得這個問題很有趣。您能否爲我們的非Clojure開明添加Clojure等價物,以及爲了語法/簡短比較的緣故? :D – epidemian 2012-03-30 00:14:04

+0

對不起,我想,這只是我不能。在網站http://clojure.org/protocols上有一個非常相似的示例,但現在我無法測試等效代碼,因此我不想發佈一些可能無法使用的代碼。令人遺憾的是,沒有像Groovy Web控制檯那樣的Web控制檯(try-clojure.org上有一個控制檯,但我甚至沒有用新行分隔的代碼行來粘貼)。 – Ice09 2012-03-30 00:31:20

+0

也許試試[ideone](http://ideone.com/)? – epidemian 2012-03-30 01:41:07

回答

10

下面是一個使用協議大致相當於Clojure的代碼:

(defprotocol Lowerable 
    (lower [x])) 

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

(lower "HELLO") 
=> "hello" 

的關鍵區別需要注意的Clojure協議(我相信讓它從Groovy的類別版本特色)

  • Clojure的協議定義不包含任何實現(它更像是這方面的接口)。該實現是分開提供的:您可以將Lowerable協議擴展到許多不同的類,而無需對類本身或協議定義進行任何更改。例如,您可以將lower定義爲Rope
  • 您上面的Groovy類別專門用於字符串 - Clojure協議並非如此。在這個例子中,Clojure協議「Lowerable」的定義沒有說明任何關於參數的類型。
  • lower是一個合適的頭等功能。因此,您可以使用它來構建更高階的抽象(通過更高階的函數),然後接受任何可擴展Lowerable協議的參數。
  • Clojure協議經過大量優化,因爲它們旨在利用JVM的快速方法分派。因此,他們被編譯到非常高效的代碼(也就是不需要動態對象檢查或反射)

Clojure的協議實際上是一個相當獨特的solution to the Expression Problem(鏈接的視頻是非常有趣)。我認爲與另一種語言中最接近的Clojure協議實際上是Haskell類型類。儘管如此,Haskell是靜態類型的並且Clojure是動態類型的,所以它有點牽強。......

+0

謝謝,這是一個很好的解釋,不同的實現實際上更強大。但是,我將不得不嘗試{{Mixing}},{{Delegate}}和{{Category}}方法,但即使它可能起作用,Protocol Protrach看起來也更接近。我呃,你不介意我用ideone-Link解決方案(和一個附加的println)來解決我的問題,以便澄清。 – Ice09 2012-03-30 09:05:02

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 

實現可用於任何類型的在任何時候加入 - 沒有必要爲這兩種實現我寫以任何方式進行合作。

但是,我不明白Groovy足以就這個問題本身提出任何實質性評論;我只能幫助描述這個問題的Clojure方面。

+0

很好的簡短例證來證明這一點。 – Ice09 2012-03-30 09:07:21