Clojure: отдых против следующего - PullRequest
64 голосов
/ 26 ноября 2010

Мне трудно понять разницу между rest и next в Clojure. Официальная страница сайта о лени указывает, что, вероятно, следует использовать rest, но в действительности это не объясняет четко разницу между ними.Кто-нибудь может дать некоторое представление?

Ответы [ 4 ]

61 голосов
/ 27 ноября 2010

Как вы описали на странице, на которую вы ссылались, next строже, чем (новое поведение) rest, потому что она должна оценить структуру ленивых минусов, чтобы узнать, возвращать ли nil или последовательность * 1004.*

rest, с другой стороны, всегда возвращает seq, поэтому ничего не нужно оценивать, пока вы на самом деле не используете результат rest.Другими словами, rest более ленив, чем next.

30 голосов
/ 27 ноября 2010

Это просто, если у вас есть:

(next '(1))
=> nil

Итак, next смотрит на следующую вещь, и если строка пуста, она возвращает nil вместо пустой последовательности. Это означает, что ему нужно смотреть в будущее (к первому элементу, который он должен вернуть), что делает его не полностью ленивым (может быть, вам не нужно следующее значение, но next тратит время на вычисления, чтобы заглянуть в будущее).

(rest '(1))
=> ()

rest не смотрит в будущее и просто возвращает оставшуюся часть последовательности.

Может быть, вы думаете, зачем вообще использовать две разные вещи здесь? Причина в том, что вы обычно хотите знать, не осталось ли ничего в seq, и просто возвращаете nil, но в некоторых случаях, когда производительность очень важна, и оценка еще одного элемента может означать огромные усилия, которые вы можете использовать rest.

21 голосов
/ 05 мая 2011

next похоже на (seq (rest ...)).

rest вернет оставшуюся часть последовательности.Если этот фрагмент последовательности еще не реализован, rest не вызывает его.Он даже не скажет вам, осталось ли в последовательности больше элементов.

next делает то же самое, но затем заставляет реализовать хотя бы один элемент последовательности.Поэтому, если next возвращает nil, вы знаете, что в последовательности больше не осталось элементов.

2 голосов
/ 13 февраля 2016

Теперь я предпочитаю использовать next с рекурсией, поскольку escape-оценка проще / чище:

(loop [lst a-list]
    (when lst
        (recur (next lst))

против

(loop [lst a-list]
    (when-not (empty? lst)   ;; or (when (seq? lst)
        (recur (rest lst))

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

...