Clojure Multimethods vs. Protocolos.
(4)
Como mencionó Arthur, los métodos múltiples son más poderosos y más caros. De hecho, los protocolos pueden considerarse como un caso especial de métodos mutuos en los que la función de envío es de class
. Por supuesto, este no es realmente el caso, ya que los protocolos son más que eso.
Si necesita enviar algo distinto a la clase del primer argumento, deberá usar un método múltiple o un nuevo diseño. El despacho por tipo es un buen caso de uso para los protocolos.
Soy un novato de Clojure y buscaba algunos ejemplos concretos de cuándo usar los protocolos y cuándo usar los métodos múltiples. Sé que los protocolos generalmente están orientados hacia la creación de una jerarquía de tipos y cosas típicas de POO, que se agregaron al lenguaje después de los métodos múltiples y que los protocolos generalmente tienen un mejor rendimiento, por lo que mi pregunta es:
¿Están los protocolos destinados a reemplazar los métodos múltiples? Si no, ¿podría darme un ejemplo en el que usaría métodos múltiples en lugar de protocolos?
Los métodos múltiples son más poderosos y más caros,
use los protocolos cuando sean suficientes, pero si necesita un envío basado en la fase de la luna como se ve desde Marte, entonces los métodos múltiples son su mejor opción.
Los protocolos existen para permitir que las cosas simples se mantengan simples y proporcionar una manera para que el código genere de manera muy parecida al mismo bytecode que el java equivalente. Parece que la mayoría de la gente usa protocolos la mayor parte del tiempo. Utilizo los métodos múltiples cuando necesito enviar más de un argumento, aunque debo admitir que esto solo ocurrió una vez, y que las jerarquías completas de isa
se usan con menos frecuencia (por mi parte). así que en breve use Multimethods cuando los necesite
el mejor ejemplo en mi experiencia es justo al principio, en core.clj
Los protocolos y métodos múltiples son complementarios y están diseñados para casos de uso ligeramente diferentes.
- Los protocolos proporcionan un envío polimórfico eficiente basado en el tipo del primer argumento. Debido a que es capaz de explotar algunas funciones de JVM muy eficientes, los protocolos le brindan el mejor rendimiento .
- Los métodos múltiples permiten un polimorfismo muy flexible que puede enviarse en función de cualquier función de los argumentos del método. Los métodos múltiples son más lentos pero muy flexibles.
En general, mi consejo es utilizar protocolos a menos que tenga un caso específico que requiera múltiples métodos.
Un caso en el que podría requerir métodos múltiples es algo como lo siguiente:
(defn balance-available? [amount balance] (> balance amount))
(defmulti withdraw balance-available?)
(defmethod withdraw true [amount balance]
(- balance amount))
(defmethod withdraw false [amount balance]
(throw (Error. "Insufficient balance available!")))
Tenga en cuenta que no puede usar los protocolos aquí por las siguientes razones:
- La función de envío necesita usar ambos argumentos para determinar qué implementación de método usar (es decir, es un caso de envío múltiple).
- Tampoco se puede distinguir en el tipo del primer argumento (que presumiblemente siempre es un valor numérico)
Me gustan los métodos múltiples cuando de otro modo no necesitas una jerarquía de clases. Por ejemplo, si tiene una base de datos de medios y sus registros son como {:media-type :video, :bytes ...}
entonces puede tener un método múltiple
(defmulti make-grayscale :media-type)
Entonces puedes hacer varias
; in video.clj
(defmethod make-grayscale :video [record]
(ffmpeg ... (:bytes record))
; in photo.clj
(defmethod make-grayscale :photo [record]
(imagemagick ... (:bytes record))
De esa manera, puede evitar tener una expresión central, para obtener la modularidad de las clases. Pero no tiene que pasar por toda esa placa de la "jerarquía de clase de envoltura", lo que para mí es una pesadilla que debería dejarse para el mundo Java. Los métodos múltiples son solo funciones y me parecen más curiosos.