2015-12-27 3 views
4

Почему вторая операция вычисляется как false? Влияет ли аргумент «или» в clojure по-разному? Если да, то как мне написать операцию, чтобы она вычисляла значение true, независимо от того, где находится 0 в аргументе?Как «или» работает в Clojure?

(= (or 0 1) 0) ; true 

(= (or 1 0) 0) ; false 
+0

Clojure обычно имеет дело с _truthy_ и _falsy_, как указано ниже. Если вы хотите 'true' /' false', функция 'boolean' будет принудительно работать с логикой. '(boolean 0)' дает 'true'. '(boolean nil)' дает 'false'. http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/boolean –

ответ

3

or не является функцией - это макрос. он расширяется до if звонков и тем самым применяются правила if: nil или false являются плоскими, все остальное правдиво - в том числе 0.

user=> (when 0 (println "true")) 
true 
nil 

Ваш код расширяется:

user=> (macroexpand '(or 1 0)) 
(let* [or__4238__auto__ 1] (if or__4238__auto__ or__4238__auto__ (clojure.core/or 0))) 

Короче говоря, or «s сгенерированный код возвращает первый аргумент - truthy или последний.

Так что, если вы хотите знать, если ваш список там содержится какой-либо ноль использовать что-то более подходящее:

user=> (some zero? [1 2 3]) 
nil 
user=> (some zero? [1 2 0]) 
true 

Или в случае 0 существует парам тоже:

user=> (some #{0} [1 2 3]) 
nil 
user=> (some #{0} [1 2 0]) 
0 
+0

Альтернатива, если у вас есть выбор типа коллекции, набор может действовать как функция и проверять членство. '(# {1 2 3} 0)' дает 'nil'. '(# {1 2 0} 0)' дает '0'. –

3

или возвращает первое недопустимое значение или false. Итак, в ваших примерах или вернем первое число в списке аргументов, ноль или иначе.

5

(or)(or x)(or x & next) - оценивает выражения по одному, слева направо.

Если форма возвращает логическое истинного значения, or возвращает это значение и не оценивает любые другие выражения, в противном случае она возвращает значение последнего выражение или nil, если последнее выражение является falsy (Источник: Clojure documentation) ,

В первом заявлении (= (or 0 1) 0) (или 0 1) вернуть 0, потому что это логично true (в Clojure и внутренне nilfalse являются falsy), а затем сравнить с 0 таким результатом является true.

Во втором заявлении (= (or 1 0) 0) он возвращает 1 и сравнивает его с 0 и возвращает false, потому что они не равны.

3

В Clojure nil и false являются фальшивыми, все остальное правдиво.

Если вы хотите, чтобы результат выражения был истинным, когда в списке есть нуль, вы должны проверить, являются ли некоторые элементы списка равными нулю. (some zero? [0 1])

2

Вы проверяете логические значения для равенства. Это запах кода на большинстве языков и хуже в Clojure.

(or 0 1) ; 0 
(or 1 0) ; 1 

...поскольку оба значения 0 и 1 логически верны, а or возвращает свой первый логически истинный аргумент (или последний аргумент, если нет истинного). Единственными вещами, которые не соответствуют действительности, являются nil и false (и его бокс-форму Boolean/FALSE).

Тот факт, что or является макросом, является случайным в этом случае.

Смежные вопросы