2010-06-03 4 views
20

Из того, что я понимаю применительно, он распаковывает список и превращает элементы в аргументы для функции.Почему в Clojure не работает (применяется или [истина ложь])?

Я вижу, что (применяется + [1 2 3]) работает, как ожидалось, то есть эквивалентно (+ 1 2 3).

Почему тогда (применить или [истинное ложное]) недействительно? Разве это не эквивалентно (или истинному ложному)?

ответ

19

Потому что or - это макрос, а не нормальная функция. Вы можете получить тот же эффект с (some identity [true false]).

+0

Ах. Благодаря! Можете ли вы придумать какие-либо альтернативы? – TriArc

+3

'(уменьшить # (или% 1% 2) false [true false ...])' –

+1

Я думал, что 'some' был' (первый фильтр) 'сам, пока Chouser любезно заставил меня увидеть более сложную реальность. Попробуйте '(некоторые: a [{: a false} {: a nil} {: a true}]), а затем замените' some' на '(comp first filter)'. –

4

В качестве альтернативы или вы можете использовать ( предикат coll).

clojure.core/некоторые ([пред Coll])
Возвращает первый логический истинное значение из (Pred х) для любого х в Coll, иначе NIL. Один общий идиома использовать набор , как ПРЕД, например это будет возвращение: Фрэд, если: Фреда находится в последовательности, в противном случае ноль (некоторые # {: Фрэд} Coll)

3

Вы можете попробовать некоторые с правдой? и ложь? предикаты,

 

user=> (some true? [true false false]) 
true 
user=> (not (some true? [true false false])) 
false 
user=> (some false? [true false false]) 
true 
user=> (not (some false? [true false false])) 
false 
 
+0

остерегайтесь фальшивых ?! (false? nil) возвращает false, несмотря на то, что nil считается ложным. (boolean nil) возвращает false. – cgrand

0

или макрос, который вы не можете использовать в качестве значения.

Создать анонимную функцию, расширяя или в выполнения через Eval:

(apply #(eval (list* 'or %&)) [true false]) 
+1

Так как вы можете получить тот же результат более естественно без макросов (делая # (или% 1% 2) false ...) '), это один из случаев, когда использование' eval' - плохая идея. Пример: ваша форма не делает то, что 'или' делает. Попробуйте использовать его на вектор '['(или) false]', например. –

0

Одна из важных вещей, чтобы отметить, хотя это модель оценки. or короткое замыкание, поэтому: (or true :some random expression that never gets evaluated:) никогда не оценивает последнее. or традиционно используется как структура управления как «логическая» или «логическая».

В традиционной модели (f x y z) оцениваются x, y и z, а f применяется к ним.

При использовании (apply f vec) содержание вектора не оценено, они взяты как есть. Это наиболее четко видно с помощью вектора символов, они не оценивают в этом контексте их привязки. Тем не менее, это запутывается тем фактом, что модель Клоджуре для создания вектора - это нечто иное, чем другие листки, [a b c d] дает вектор, который содержит оценки символов a, b, c и d. Контрастность большинства Lisps, где #(a b c d) не оценивает символы и просто идентична оценке (vector 'a 'b 'c 'd) (или фактически (apply vector '(a b c d))).

Так что, даже если бы можно было применять специальные синтаксические формы, результат был бы непрозрачной семантикой. or сначала оценивает свой первый аргумент, если true, он останавливается и возвращает это, иначе он переходит ко второму и повторяется до последнего. В случае применения аргументы уже оцениваются, если они затем оценивают второй раз? Скорее всего, это приводит к ошибке во время выполнения?

С точки зрения реализации, это было бы очень выгодно, если бы синтаксис был также «объектами» и требовал бы гораздо более сложной оценочной модели. Таким образом, они не разрешаются во время выполнения, а скорее переписываются компилятору во время компиляции.

Но, по этой причине, когда or используется логически, а не в качестве структуры управления, я сам нахожу это удобно иметь функции or/f, and/f, if/f и так далее доступны, которые являются истинными процедуры и оценить все их аргументы и, следовательно, может применяться.

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

  • Нет связанных вопросов^_^