Clojure: проверьте, что предикат выполняется ровно один раз - PullRequest
0 голосов
/ 08 марта 2020

Есть ли в Clojure какая-либо функция, подобная every? или some, за исключением проверки того, что предикат хранится ровно один раз?

Например:

(once? even? '(1 2 1)) => true
(once? even? '(2 2 1)) => false

Ответы [ 3 ]

1 голос
/ 08 марта 2020

Я не знаю ни одной подобной функции в clojure.core, и я не сталкивался с существующей библиотекой, которая рекламирует это.

Глядя на реализацию some в clojure.core, она использует recur, но для once? вам понадобится механизм, чтобы запомнить, если вы видели значение true ранее. Делать это внутреннее значение видимым в виде трехчастного вызова кажется уродливым Кроме того, я хотел бы избежать полного обхода коллекции, если в этом нет необходимости.

Следовательно, я бы go с уменьшением:

(defn once? [pred coll]
  (reduce 
    (fn once-reduce-fn [seen-true it]
      (if (pred it)
        (if seen-true 
          (reduced false)
          true)
        seen-true))
  false
  coll))

;; You can use this code under the Apache Software License 2.0 
;; in addition to StackOverflow defaults

Прекращает итерацию коллекции, когда видит второй истинный результат предиката, который также работает с пустыми коллекциями или nil.

1 голос
/ 08 марта 2020

Еще проще:

(defn once?
  [f coll]
  (= 1 (count (filter boolean (map f coll)))))  ; or change `boolean` => `identity`

с результатом:

(once? even? [1 2 1]) => true
(once? even? [2 2 1]) => false
0 голосов
/ 08 марта 2020

Вы можете сделать один:

(defn once? [f xs]
            (= 1 (get (frequencies (map f xs)) true)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...