Подтвердить что ты не робот

Почему в Clojure не работает (применяется или [истина ложь])?

Из того, что я понимаю применительно, он распаковывает список и превращает элементы в аргументы для функции.

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

clojure.core/some ([pred coll])
Возвращает первое логическое истинное значение of (pred x) для любого x из coll, иначе ноль. Одной из распространенных идиом является использование набора как пред, например, это будет return: fred if: fred находится в последовательность, иначе nil: (некоторые # {: fred} 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

Ответ 4

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

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

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

Ответ 5

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

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

При использовании (apply f vec) содержимое вектора не оценивается, они берутся как есть. Это наиболее четко видно с помощью вектора символов, они не оценивают в этом контексте их привязки. Тем не менее, это запутывается тем фактом, что модель w120 > для создания вектора - это то, что отличается от других lisps, [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 и т.д., которые истинны процедуры и оценивать все их аргументы и, следовательно, могут быть применены.