2012-01-11 19 views

Respuesta

21

Si bien es difícil discutir con la concisión en las otras respuestas , .. ha algo caído de favor, reemplazado por el más versátil ->. Personalmente prefiero:

(-> (NutritionFacts$Builder. 240 8) 
    (.calories 100) 
    (.sodium 350) 
    (.carbohydrates 27) 
    (.build)) 

Es un par de caracteres, pero se gana dos cosas:

  • Explícito. Puedo mirar la línea de sodio (por ejemplo) y decir que es una llamada al método Java, porque el . está ahí.
  • Flexibilidad. Si es necesario, puedo encadenar una llamada que no sea de método en el centro (por ejemplo, imprimirlo en stdout) o, al final de todo esto, pasarlo a otra llamada de función.

más importante, cada otra respuesta a esta pregunta ha conseguido el mal nombre de clase: NutritionFacts.Builder de Java es el lenguaje de azúcar sobre la clase de bienes JVM llamado NutritionFacts $ constructor, y que la clase es la que debe referirse a Clojure (ya no estamos usando javac para compilar nuestro código).

estoy en desacuerdo con la sugerencia doto: funciona sólo porque esta clase Constructor pasa a aplicar su método en cadena mediante la mutación de una sola instancia y luego devolverlo. doto es ideal para objetos de Java que requieren mutación en el lugar, pero cuando una clase tiene la amabilidad de pretender que es inmutable, realmente deberías estar usando la versión de encadenamiento de métodos (es decir, ->).

3

sólo estoy empezando con Clojure, pero parece que la invocación de métodos estándar para mí:

(doto 
    (NutritionFacts.Builder. 240 8) 
    (.carbohydrates 27) 
    (.sodium 35) 
    (.calories 100) 
    (.build) 
) 

EDITAR :
Como señala @Goran Jovic, esto llama a todos los métodos del objeto creado en el primer formulario.
Por lo tanto, funciona en este caso ya que el código de Java usa el método de encadenamiento, pero no es más aplicable en general.

+0

La única razón por la que no es idiomático se debe a que mutar una var en varias formas diferentes. Sólo se envuelve en un [doto] (https://github.com/clojure/clojure/blob/f5f827ac9fbb87e770d25007472504403ed3d7a6/src/clj/clojure/core.clj # L3395) ¡y está bien! –

+0

@Goran Jovic He cambiado el código como sugirió. ¡Gracias! –

+0

Sí, eso es todo. Tenga en cuenta que la principal diferencia entre 'doto' y' ..' es que 'doto' llama a métodos en un objeto definido por el primer formulario, y' ..' hace cada invocación sobre el resultado del anterior. En este caso, es lo mismo, ya que los métodos de Java siguen devolviendo el objeto que se está creando. –

2

(.. (NutrionalFacts.Builder. 240 8) (calories 100) (sodium 35) (carbohydrates 27) (build))

8

Uso .. macro. Son dos puntos consecutivos. Le permite justo lo que necesita: llamar consecutivamente al siguiente método Java sobre el resultado del anterior.

no tengo un REPL alrededor, pero su línea debería traducirse en algo así como:

(.. (NutritionFacts.Builder. 240 8) 
    (calories 100) 
    (sodium 350) 
    (carbohydrates 27) 
    (build)) 
0

Este hilo es un par de años de edad, y la macro-hilo primero sigue siendo preferida forma que lo que yo puedo decir, pero no se necesita la sintaxis $. La barra (/) funciona así:

(-> (Caffeine/newBuilder) 
     (.maximumSize 10000) 
     (.build)) 
+0

'(Caffeine/newBuilder)' es una llamada a un método estático (Java 'Caffeine.newBuilder()') mientras que '(NutritionalFacts $ Builder.)' Es una llamada al constructor de una clase estática (Java 'new NutritionalFacts. Builder() '), entonces esto realmente no es diferente de la respuesta aceptada. – glts

+0

ahh, ok. pensé que había alguna actualización para la sintaxis. Gracias – Alex

Cuestiones relacionadas