Не макро-версии clojure "и" и "или" - PullRequest
7 голосов
/ 03 апреля 2011

Есть ли в Clojure версии не-макроса and и or?

Обновление: в этом случае меня не волнует короткое замыкание.

Ответы [ 5 ]

8 голосов
/ 04 апреля 2011

or

Функция some "Возвращает первое логическое истинное значение (pred x) для любого x в coll, иначе nil."

Так что вы можете использовать (some identity coll) для or.Обратите внимание, что его поведение будет отличаться от or, когда последнее значение будет false: оно вернет nil, где or вернет false.

and

Если вам не нужно знать значение последней формы в векторе coll, вы можете использовать (every? identity coll) для and.Это будет отличаться от поведения макроса and тем, что он возвращает true, если все его аргументы верны.См. Ответ Ларсмана, если вам нужен результат последней формы.

5 голосов
/ 04 апреля 2011

Пусть land обозначает «логическое и», тогда их тривиально определить:

(defn land
  ([] true)
  ([x & xs] (and x (apply land xs))))

Или, немного ближе к стандартному поведению and:

(defn land
  ([] true)
  ([x] x)
  ([x & xs] (and x (apply land xs))))

и аналогично для or.

3 голосов
/ 04 апреля 2011

Это на самом деле недавно появилось как тема на clojure-dev.Рич Хикки в конечном итоге пришел к выводу, что они должны быть добавлены в ядро ​​для 1.3 как каждый и любой pred (зарегистрированный как CLJ-729 ).Я думаю, что дальнейшие дискуссии привели их к тому, чтобы их теперь называли Every-pred (вариант и) и some-fn (вариант или).Финальная версия была только недавно передана мастеру.

1 голос
/ 04 апреля 2011

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

(defn &&* [& fns]
  (cond (= 1 (count fns)) ((first fns))
        :otherwise
        (and ((first fns)) (apply &&* (next fns)))))

(defn ||* [& fns]
  (cond (= 1 (count fns)) ((first fns))
        :otherwise
        (or ((first fns)) (apply ||* (next fns)))))

Example use:

(map 
  (partial apply &&*) 
    (map (partial map constantly) ;; thunk all of these values 
      [["yes" "no"] 
       [false true]
       [true "something"] 
       [true "something" "false"]]))

("no" false "something" "false")

Другой пример:

(defmacro thunks
  "convert expressions into thunks to prevent advance evaluation"
  [& exprs]
  (let [fns# (map (fn [e] `(fn [] ~e)) exprs)]
    (cons 'vector fns#)))

(apply ||* (thunks (+ 1 2) false (* 1 5)))
3
(apply &&* (thunks (+ 1 2) false (* 1 5)))
false
(apply &&* (thunks (+ 1 2) (* 1 5)))
5
1 голос
/ 03 апреля 2011

Если вы имеете в виду функции: нет, и они не могут быть.Причина в том, что формы функций всегда оценивают все свои аргументы перед применением функции к их значению.Вы не хотите этого здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...