Clojure применить против карты - PullRequest
30 голосов
/ 22 февраля 2010

У меня есть последовательность (foundApps), возвращенная из функции, и я хочу отобразить функцию на все ее элементы. По какой-то причине apply и count работают на последовательность, но map не работает:

(apply println foundApps)
(map println rest foundApps)
(map (fn [app] (println app)) foundApps)
(println (str "Found " (count foundApps) " apps to delete"))))

Печать:

{:description another descr, :title apptwo, :owner jim, :appstoreid 1235, :kind App, :key #<Key App(2)>} {:description another descr, :title apptwo, :owner jim, :appstoreid 1235, :kind App, :key #<Key App(4)>}
Found 2 apps to delete for id 1235

Так что apply, кажется, с удовольствием работает для последовательности, но map не работает. Где я глупый?

Ответы [ 3 ]

32 голосов
/ 22 февраля 2010

Скорее всего, вас поражает лень map. (map создает ленивую последовательность, которая реализуется только тогда, когда некоторый код на самом деле использует его элементы. И даже тогда реализация происходит по частям, так что вам нужно пройти всю последовательность, чтобы убедиться, что все это реализовано.) Попробуйте обернуть map выражение в dorun:

(dorun (map println foundApps))

Кроме того, поскольку вы делаете это только для побочных эффектов, может быть, лучше использовать doseq вместо:

(doseq [fa foundApps]
  (println fa))

Обратите внимание, что (map println foundApps) должен прекрасно работать в REPL; Я предполагаю, что вы извлекли это откуда-то в вашем коде, где это не принудительно. Нет такой разницы с doseq, который является строгим (то есть, не ленивым) и будет проходить последовательности аргументов для вас при любых обстоятельствах. Также обратите внимание, что doseq возвращает nil в качестве значения; это хорошо только для побочных эффектов. Наконец я пропустил rest из вашего кода; Вы могли иметь в виду (rest foundApps) (если это не просто опечатка).

Также обратите внимание, что (apply println foundApps) будет печатать все foundApps в одной строке, тогда как (dorun (map println foundApps)) будет печатать каждый элемент foundApps в отдельной строке.

21 голосов
/ 21 августа 2015

У меня есть простое объяснение, которого нет в этом посте. Давайте представим абстрактную функцию F и вектор. Таким образом,

(apply F [1 2 3 4 5])

переводится как

(F 1 2 3 4 5)

, что означает, что F должно быть в лучшем случае переменным.

В то время как

(map F [1 2 3 4 5])

переводится как

[(F 1) (F 2) (F 3) (F 4) (F 5)]

, что означает, что F должно быть одной переменной или, по крайней мере, вести себя так.

В типах есть некоторые нюансы, поскольку map на самом деле возвращает ленивую последовательность вместо вектора. Но ради простоты я надеюсь, что это простительно.

8 голосов
/ 22 февраля 2010

Небольшое объяснение может помочь. Обычно вы используете apply, чтобы разделить последовательность элементов на набор аргументов функции. Поэтому применение функции к некоторым аргументам означает просто передачу их в качестве аргументов функции в одном вызове функции.

Функция map будет делать то, что вы хотите, создайте новый seq, подключив каждый элемент ввода в функцию, а затем сохраните результат. Он делает это лениво, поэтому значения будут вычисляться только тогда, когда вы фактически выполняете итерацию по списку. Для этого вы можете использовать функцию (doall my-seq), но в большинстве случаев вам не нужно этого делать.

Если вам нужно немедленно выполнить операцию, потому что она имеет побочные эффекты, такие как печать или сохранение в базе данных или что-то еще, то вы обычно используете дозаq.

Итак, чтобы добавить «foo» ко всем вашим приложениям (при условии, что они являются строками):

(карта (fn [app] (str app "foo")) found-apps)

или использование сокращения для анонимной функции:

(map # (str% "foo") found-apps)

Выполнить то же самое, но распечатать сразу, можно с помощью любого из этих:

(doall (map # (println%) found-apps))

(drugq [app found-apps] (приложение println))

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