Используя Clojure, как мне создать следующий объект? Объект взят из java-кода (From Effective Java):
NutritionFacts cocaCola =
new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();
Используя Clojure, как мне создать следующий объект? Объект взят из java-кода (From Effective Java):
NutritionFacts cocaCola =
new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();
Несмотря на то, что в других ответах с консигментом трудно ответить 1..
несколько отпал в пользу, заменил более универсальный ->
. Лично я предпочитаю:
(-> (NutritionFacts$Builder. 240 8)
(.calories 100)
(.sodium 350)
(.carbohydrates 27)
(.build))
Это еще несколько персонажей, но вы получаете две вещи:
.
.Самое главное, что каждый другой ответ на этот вопрос получил неправильное имя класса: Java NutritionFacts.Builder - это язык сахара над реальным классом JVM с именем NutritionFacts $Builder, и этот класс должен соответствовать Clojure (поскольку мы не используют javac для компиляции нашего кода).
1 Я не согласен с предложением doto
: он работает только потому, что этот класс Builder реализует свою цепочку методов, изменяя один экземпляр и затем возвращая его. doto
отлично подходит для объектов Java, для которых требуется мутация на месте, но когда класс достаточно любезен, чтобы притворяться неизменным, вы действительно должны использовать версию метода-цепочки (т.е. ->
).
Используйте макрос ... Это две последовательные точки. Он позволяет только то, что вам нужно - последовательно вызвать следующий метод Java в результате предыдущего.
У меня нет REPL вокруг, но ваша строка должна перевести на что-то вроде:
(.. (NutritionFacts.Builder. 240 8)
(calories 100)
(sodium 350)
(carbohydrates 27)
(build))
Я только начинаю с Clojure, но он выглядит как вызов стандартного метода для меня:
(doto
(NutritionFacts.Builder. 240 8)
(.carbohydrates 27)
(.sodium 35)
(.calories 100)
(.build)
)
EDIT:
Как указывает @Goran Jovic, это вызывает все методы для объекта, созданного в первой форме.
Таким образом, он работает в этом случае, поскольку код Java использует цепочку методов, но не является более общеприменимым.
(.. (NutrionalFacts.Builder. 240 8) (calories 100) (sodium 35) (carbohydrates 27) (build))
Этот поток пару лет, и макрос нити-первого по-прежнему предпочтительнее, насколько я могу сказать, но синтаксис $не нужен. Слэш (/) работает также:
(-> (Caffeine/newBuilder)
(.maximumSize 10000)
(.build))