2012-03-29 10 views
8

Al haber visto recientemente una presentación de los protocolos de Clojure, quedé bastante impresionado por la manera limpia en que las extensiones a los tipos existentes se pueden hacer de esta manera. Sin embargo, estaba bastante seguro de haber visto una forma similar de hacer esto en otro idioma y después de un tiempo descubrí que era Groovy Categories.Diferencia entre los protocolos de Clojure y las categorías de Groovy

Compare esto:

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

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

al equivalente Protocolo Clojure (tomado de mikera's answer below and tested in ideone.com)

(defprotocol Lowerable 
    (lower [x])) 

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

(println (lower "HELLO")) 

mi pregunta es:

  1. , además de las diferencias de rendimiento (se dice que Clojure está muy optimizado en este sentido) - ¿hay una diferencia semántica entre los dos enfoques? ches?
  2. Además de la sintaxis torpe, ¿hay algo lógicamente incorrecto con el enfoque de Groovy?

Descargo de responsabilidad: Soy un completo Clojure novato!

+0

Encuentro esta pregunta bastante interesante. ¿Podría agregar el equivalente de Clojure para los que no están iluminados por Clojure, y para las comparaciones de sintaxis/brevedad? : D – epidemian

+0

lo siento, me gustaría, es solo que no puedo. En el sitio http://clojure.org/protocols hay una muestra bastante similar, pero en este momento no puedo probar el código equivalente, por lo tanto, no quiero publicar ningún código que pueda no funcionar. Lamentablemente, no existe una consola web como la consola web de Groovy (hay una en try-clojure.org, pero estoy fracasando al pegar líneas de código separadas en la nueva línea). – Ice09

+0

Tal vez intente con [ideone] (http://ideone.com/)? – epidemian

Respuesta

10

Aquí está el código Clojure equivalente aproximado a través de protocolos:

(defprotocol Lowerable 
    (lower [x])) 

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

(lower "HELLO") 
=> "hello" 

Las distinciones clave a tener en cuenta sobre los protocolos de Clojure (que creo que confiere carácter distintivo de la versión categorías maravilloso)

  • el protocolo Clojure la definición no contiene ninguna implementación (es más como una interfaz a este respecto). La implementación se proporciona por separado: puede extender el protocolo de Lowerable a tantas clases diferentes como desee sin necesidad de realizar ninguna modificación a las clases en sí o la definición del protocolo. Por ejemplo, puede definir lower para trabajar en un Rope.
  • Su categoría Groovy anterior está especializada en Cadenas: este no es el caso con los protocolos Clojure. En este ejemplo, el protocolo de Clojure "Lowerable" se define sin decir nada sobre el tipo de argumentos.
  • lower es una función de primera clase adecuada. De modo que puede usarlo para crear abstracciones de orden superior (a través de funciones de orden superior) que, a su vez, aceptarán cualquier argumento al que se haya extendido el protocolo Lowerable.
  • Los protocolos Clojure están muy optimizados ya que están diseñados para explotar el rápido envío de métodos de la JVM.Ellos por lo tanto, se compilan a código muy eficiente (no hay examen dinámico objeto o reflexión requerido)

protocolos Clojure son en realidad un bastante único solution to the Expression Problem (vídeo vinculado es bastante interesante). Creo que el equivalente más cercano a los protocolos Clojure en otro idioma es en realidad las clases de tipo Haskell. Incluso entonces es un poco exagerado ya que Haskell está tipado estáticamente y Clojure está tipeado dinámicamente ...

+0

Gracias, es una buena explicación, tener diferentes implementaciones en realidad es más poderoso. Sin embargo, tendría que probar un enfoque de {{Mixing}}, {{Delegate}} y {{Category}}, pero incluso si pudiera funcionar, el approoch de Protocolos parece más cercano. Me da saltitos, no me importa que extienda mi pregunta con su solución (y una impresión adicional) en un ideone-Link para aclaración. – Ice09

5

La característica Clojure se está refiriendo a las miradas como:

(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 

implementaciones se pueden agregar para cualquier tipo en cualquier momento - no hay necesidad de que los dos implementaciones que he escrito a cooperar de ninguna manera.

Sin embargo, no entiendo el Groovy lo suficientemente bien como para hacer comentarios sustantivos sobre la pregunta en sí; Solo puedo ayudar a describir el lado Clojure de la pregunta.

+0

Buen ejemplo corto para demostrar el punto. – Ice09

Cuestiones relacionadas