К «гнездо» или повторить функцию над значением, Clojure имеет функцию iterate
. Например, (iterate inc 2)
можно рассматривать как бесконечный ленивый список [2, (inc 2), (inc (inc 2)), (inc (inc (inc 2))) ...]
(я использую скобки []
, чтобы не обозначать «список» - на самом деле они представляют собой «вектор» в терминах Clojure, но во избежание путаницы с ()
, который может обозначать список данных или s-выражение, которое должно быть вызовом функции. iterate
делает не возвращает вектор). Конечно, вам, вероятно, не нужен бесконечный список, в который входит ленивая часть. Ленточный список даст вам только то, о чем вы просите. Так что если вы спросите в течение первых десяти элементов, это то, что вы получите:
user> (take 10 (iterate inc 2))
> (2 3 4 5 6 7 8 9 10 11)
Конечно, вы могли бы попробовать попросить весь список, но будьте готовы либо перезагрузить REPL, или отправку в отдельный поток, так как этот вызов не будет конца:
user> (iterate inc 2)
> (2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
=== Shutting down REPL ===
=== Starting new REPL at C:\Users\Omnomnomri\Clojure\user ===
Clojure 1.5.0
user>
Здесь, я использую clooj, и это то, что он выглядит, когда я перезагрузить REPL. В любом случае, это все касательно. Дело в том, что iterate
отвечает на суть вашего вопроса. Другая часть, останавливаясь на каком-либо тестовом состоянии, включает take-while
. Как вы можете себе представить, take-while
много как take
, только вместо остановки после некоторого числа элементов, он останавливается на какой-то условия испытания (или в Clojure просторечии предикат):
user> (take-while #(< % 10) (iterate inc 2))
> (2 3 4 5 6 7 8 9)
Обратите внимание, что take-while
является эксклюзивным с его предикатным тестом, так что здесь, как только значение завершит тест (менее 10), оно исключает это значение и включает только предыдущие значения в возвращаемом результате. На данный момент, решая свой пример довольно straightfoward:
user> (take-while #(< % 7) (iterate inc 2))
> (2 3 4 5 6)
И если вам это нужно, чтобы быть вектором, обернуть все это в вызове vec
:
user> (vec (take-while #(< % 7) (iterate inc 2)))
> [2 3 4 5 6]