Что такое идиоматический Clojure для foo = bar || баз?

Я хочу указать значение по умолчанию, которое можно переопределить. Я знаю, что могу использовать тройку, например:

(def foo (if (not (nil? bar)) bar baz))

Но, конечно же, в Clojure есть более идиоматический способ сказать «используйте bar или baz, если bar равен нулю».

Какие-либо предложения?


person Josh Glover    schedule 14.04.2012    source источник


Ответы (3)


Это назначит bar, если это не nil или false, и baz в противном случае.

(def foo (or bar baz))

ИЗМЕНИТЬ

Если вы хотите точно проверить nil, вы можете немного оптимизировать исходный код, например:

(def foo (if (nil? bar) baz bar))

Я считаю, что это кратчайший путь, хотя и не идиоматический.

person bereal    schedule 14.04.2012
comment
Это здорово и решит проблему, с которой я сталкиваюсь в своем коде, но я также хотел бы знать идиому для различения nil и false при этом. - person Josh Glover; 14.04.2012
comment
@JoshGlover Ну, я не уверен, что для этого есть специальная идиома, но если вы поменяете местами bar и baz, например, (if (nil? bar) baz bar)), вы избавитесь от not, и он вряд ли станет короче. - person bereal; 14.04.2012
comment
Хорошее замечание, и очень даже приятное. Спасибо! Если вы обновите свой ответ, чтобы показать это, я приму его. - person Josh Glover; 14.04.2012

В вашем вопросе конкретно не говорится о нескольких переменных, но если вы хотите, чтобы это значение по умолчанию использовалось более чем для одной переменной, идиоматический способ сделать это - использовать деструктурирование на карте со значениями по умолчанию :or.

например Возьмите эту функцию, которая принимает аргумент карты m, ожидаемая карта имеет ключи :a, :b и :c, но если :b и/или :c не указаны, то значения по умолчанию берутся из предложения :or

(defn foo [m]
    (let [{:keys [a b c], :or {b 100 c 200}} m]
      (println "a:" a)
      (println "b:" b)
      (println "c:" c)))

user> (foo {:a 1 :b 2})
a: 1   ; no default, use supplied value
b: 2   ; value supplied, default ignored
c: 200 ; no value supplied, use default from :or
nil
person sw1nn    schedule 14.04.2012

fnil тоже вариант:

user> (def default-to (partial fnil identity))
#'user/default-to

user> (let [bar :foo
            baz :default]
        ((default-to baz) bar))
:foo

user> (let [bar nil
            baz :default]
        ((default-to baz) bar))
:default
person Brian Carper    schedule 16.04.2012