'map' и 'for' для понимания последовательности - PullRequest
0 голосов
/ 25 апреля 2018

Я начал изучать Clojure два дня назад, без какого-либо опыта функционального программирования. Сегодня, читая чтение книги Программирование Clojure , я столкнулся с проблемой.

Речь идет о последовательности преобразования . Вот пример:

(map #(format ​"<%s>%s</%s>"​ %1 %2 %1)
    [​"h1"​ ​"h2"​ ​"h3"​ ​"h1"​] [​"the"​ ​"quick"​ ​"brown"​ ​"fox"​])

, который дает результат:

-> (​"<h1>the</h1>"​ ​"<h2>quick</h2>"​ ​"<h3>brown</h3>"​ "<h1>fox</h1>​"​)

Мне не так сложно это получить. На самом деле, проблема возникает, когда книга говорит мне, что мы можем использовать for для общего понимания последовательности, а затем показывает мне пример. Этот пример довольно прост, и я могу его полностью понять.

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

Я мог бы просто получить:

("<h1>the</h1>"
"<h1>quick</h1>"
"<h1>brown</h1>"
"<h1>fox</h1>"
"<h2>the</h2>"
"<h2>quick</h2>"
"<h2>brown</h2>"
"<h2>fox</h2>"
"<h3>the</h3>"
"<h3>quick</h3>"
"<h3>brown</h3>"
"<h3>fox</h3>"
"<h1>the</h1>"
"<h1>quick</h1>"
"<h1>brown</h1>"
"<h1>fox</h1>")

с переписанным кодом:

(for [label ["h1" "h2" "h3" "h1"] word ["the" "quick" "brown" "fox"]]
    (format "<%s>%s</%s>" label word label))

Мне сообщили, что, как правило, использование условия :when может как-то помочь, но я просто не могу придумать.

Как можно переписать код с for, чтобы ответ был точно таким же, как и у версии map?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Как вы видели, когда у вас есть несколько привязок в for, он действует как «вложенный цикл» в других императивных языках, как если бы у вас был внешний цикл for для label и внутренний цикл for для word. Таким образом, вы получаете каждую комбинацию значений двух коллекций.

 for (label in labels)
   for (word in words)
      print(word + " " + label);

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

(def pairs ;; a vector of tuples/pairs of labels/words
  (map vector ["h1" "h2" "h3" "h1"] ["the" "quick" "brown" "fox"]))
;; (["h1" "the"] ["h2" "quick"] ["h3" "brown"] ["h1" "fox"])
(for [[label word] pairs] ;; enumerate each pair
  (format "<%s>%s</%s>" label word label))
=> ("<h1>the</h1>" "<h2>quick</h2>" "<h3>brown</h3>" "<h1>fox</h1>")

Когда вы передаете несколько аргументов набора в map, ваша функция отображения получает элемент из каждой коллекции для каждого шага отображения. Если бы у вас была только одна входная коллекция, то эквивалент for выглядел бы очень похоже.

0 голосов
/ 25 апреля 2018

for производит декартово произведение по всем заданным последовательностям, поэтому один из способов получить соответствующие пары - использовать map-indexed:

(for [[i label] (map-indexed vector ["h1" "h2" "h3" "h1"])
      [j word] (map-indexed vector ["the" "quick" "brown" "fox"])
      :when (= i j)]
  (format "<%s>%s<%s>" label word label))

Но для этого необходимо выполнить итерацию более 16 значений, чтобы получить 4 значения, поэтому использование map с 3 аргументами является более эффективным и простым.

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