logaan
tuvo la amabilidad de dejar algunos comentarios en twitter con respecto a mi reciente post sobre refactorización en Java, Scala y Clojure. Necesitaba más de 140 caracteres, así que estoy respondiendo aquí.
Discusión
@ GlenKPeterson no creo que realmente haya explorado la problema de expresión para Clojure. . Sus funciones están vinculadas a la representación map
– logaan (@ logaan) 06 de octubre 2013
Glen respondió: (sin tipo) Clojure envuelve la función con convertidores en lugar de envolver un tipo de datos definido por el usuario. ? Vista funcional de la misma edición
logaan respondió: Mi entendimiento es que el problema de la expresión está ligada al polimorfismo. La solución de Clojure es protocolos. Protocolos permiten añadir más tipos de comportamiento existente y más comportamiento de los tipos existentes. En Scala necesita implicits.
Responder
Solución de Chris Houser al Problema Expresión en InfoQ fue una charla muy interesante y, supongo, la base para su crítica. Resulta que había un debate sobre Lambda Ultimate acerca de la naturaleza del problema de expresión en respuesta a la presentación de Chouser.
Desde Clojure rechaza escriba la seguridad como un objetivo de diseño, aplicando Clojure al problema Expresión parecía algo de un tramo para mí. Por otro lado, el artículo de Martin Odersky señala:El problema expresión de término fue acuñado originalmente por Phil Wadler en un post en la lista de distribución de Java-Genericidad, en la que también propuso una solución por escrito en un prolongado versión de Java genérico. Sólo más tarde, parecía que la solución de Wadler no podía ser escrito.
En cuanto a la necesidad de implicits de Scala para resolver el problema de la expresión, puede haber algún aspecto de esto que yo no estaba comprendiendo. En realidad, fue el papel de Odersky que me hizo pensar rasgos eran la solución a este problema. Estoy impresionado con lo bien que lo resuelven. Especialmente en comparación con toda la tipificación de Java requiere cuando tengo 8 clases que implementan una interfaz que tiene que cambiar!
En última instancia, la definición exacta del problema original de Wadler es mucho menos interesante para mí que la solución o pasos laterales este tipo general de problema. En respuesta a su crítica perspicaz, he cambiado el nombre de mi post, «Refactoring en 3 idiomas» y proporcionó una solución Clojure alternativa a continuación. Gracias de nuevo por tomarse el tiempo para responder.solución alternativa
Esta es una «solución» alternativa a mi post anterior utilizando los registros y protocolos:
( defrecord YearMonth [ años meses ])
( defprotocol MONTH_ADDIBLE
( AddMonths [ MONTH_ADDIBLE meses ]) )
( tipo ampliar YearMonth
MONTH_ADDIBLE
( AddMonths [ ym , addedMonths ]
( dejar [ NewMonth ( + ( : mes ym ) addedMonths )]
( cond ( > NewMonth 12 )
;; convertirse al mes de base cero para las matemáticas
( dejar [ m ( - NewMonth 1 )]
;; Llevar a ningún meses adicionales al ejercicio
( asoc ym : año ( + ( : año ym ) ( quot m 12 ))
: mes ( + ( rem m 12 ) 1 )))
( < NewMonth 1 )
;; Llevar a ningún meses adicionales más al año, pero la
;; primer año en este caso sigue siendo año-1
( dejar [ y ( diciembre ( + ( : año ym ) ( quot NewMonth 12 )))
;; Ajustar mes negativo para . estar dentro de un año
;; Para obtener el mes positivo, restar de 12
m ( + 12 ( rem NewMonth 12 ))]
( asoc ym : año y : mes m ))
: else ( asoc ym : mes NewMonth )))))
;; Pruebas
( AddMonths ( YearMonth. 2013 , 7 ) 2 )
;; # user.YearMonth {: año 2013,: mes 9}
( AddMonths ( YearMonth. 2012 , 12 ) 1 )
;; # user.YearMonth {: año 2013,: mes 1}
( AddMonths ( YearMonth. 2013 , 1 ) -1 )
;; # user.YearMonth {: año 2012, : mes 12}
;; Con un campo adicional
( AddMonths ( asoc ( YearMonth. 2013 , 7 ) : otherField1 " One " ) 2 )
;; # user.YearMonth {: año 2013,: mes 9,: otherField1 "Uno"}
( AddMonths ( asoc ( YearMonth. 2012 , 12 ) : otherField1 "One" ) 1 )
;; # user.YearMonth {: año 2013,: mes 1,: otherField1 "Uno"}
( AddMonths ( asoc class="p"> YearMonth. 2013 , 1 ) : otherField1 "One" ) -1 )
; ; # user.YearMonth {: año 2012,: 12 meses,: otherField1 "Uno"}
( defrecord YearMonth2 [ YYYYMM ])
( defn yearAndMonthToYm [ años meses ] ( + ( * años 100 ) meses ))
( tipo ampliar YearMonth2
MONTH_ADDIBLE
( AddMonths [ ym , addedMonths ]
( deja [ años ( quot ( : YYYYMM ym ) 100 )
NewMonth ( + ( rem ( : YYYYMM ym ) 100 ) addedMonths )]
( cond ( > NewMonth 12 )
;; convertirse al mes de base cero para matemáticas
( dejar [ m ( - NewMonth 1 )]
;; Llevar a ningún meses adicionales al ejercicio
( asoc ym : YYYYMM ( yearAndMonthToYm ( + años ( quot m 12 ))
( + ( rem m 12 ) 1 ))))
class="p"> < NewMonth 1 )
;; Llevar a ningún meses adicionales durante el año, pero la
;; primer año en este caso sigue siendo año-1
( dejar [ y ( diciembre ( + años ( quot NewMonth 12 )))
;;. Ajustar mes negativo para estar dentro de un año
;; Para obtener el mes positivo, restar de 12
m ( + 12 ( rem NewMonth 12 ))]
( asoc ym : YYYYMM ( yearAndMonthToYm y , m )))
: else ( asoc ym : YYYYMM ( yearAndMonthToYm años , NewMonth ) )))))
( AddMonths ( YearMonth2. 201307 ) 2 )
;; # user.YearMonth2 {: YYYYMM 201309}
;; Con un campo adicional
( AddMonths ( asoc ( YearMonth2 201307 ) :. otherField2 1.1 ) 2 )
;; # user.YearMonth2 {: YYYYMM 201309,: otherField2 1,1}