Clojure: Встроенные средства обхода списков, map
Любой список рано или поздно захочется обойти (traverse), то есть поработать с отдельными элементами. В процедурных языках используются циклы, но многие языки имеют и декларативные средства работы с коллекциями — map, filter, reduce. А ведь сами эти функции пришли в программирование через LISP!
Clojure тоже предоставляет полный набор таких функций. Ближайшие несколько уроков будут посвящены этим встроенным в Clojure функциям.
map
Итак, map в Clojure используется так:
(map inc (list 1 2 3)) ; '(2 3 4)Здесь inc — встроенная функция, добавляющая к числу единицу. Всё максимально предсказуемо: map превращает старый список в новый, применяя функцию к каждому элементу. Обход получается функциональный, потому что мы получаем новый список, не меняя старый.
Может map обходить и несколько списков одновременно: можно применить map к нескольким спискам, тогда функция-аргумент будет применена ко всем первым элементам, затем ко всем вторым, и так далее. Но map потребует от входных списков иметь одинаковую длину, иначе вы получите ошибку.
Вот так можно поэлементно просуммировать три списка:
(map +
(list 1 2 3)
(list 10 20 30)
(list 100 200 300))
; '(111 222 333)Заметьте, не потребовалось даже использовать анонимную функцию, которая складывала бы три числа, ведь функция "+" принимает произвольное количество аргументов!
Задание
Реализуйте функцию maps, которая должна принимать два списка — список функций и список списков аргументов — и возвращать список результатов применения функций к наборам аргументов. Вот как использование maps должно выглядеть:
(maps
(list
inc
string?)
(list
(list 10 20)
(list "a" 0)))
; '((11 21) (true false))Здесь
'(11 21), это результат примененияincк(list 10 20)'(true false), это результат примененияstring?к(list "a" 0)
Полезное
Clojure: Встроенные средства обхода списков, map
Любой список рано или поздно захочется обойти (traverse), то есть поработать с отдельными элементами. В процедурных языках используются циклы, но многие языки имеют и декларативные средства работы с коллекциями — map, filter, reduce. А ведь сами эти функции пришли в программирование через LISP!
Clojure тоже предоставляет полный набор таких функций. Ближайшие несколько уроков будут посвящены этим встроенным в Clojure функциям.
map
Итак, map в Clojure используется так:
(map inc (list 1 2 3)) ; '(2 3 4)Здесь inc — встроенная функция, добавляющая к числу единицу. Всё максимально предсказуемо: map превращает старый список в новый, применяя функцию к каждому элементу. Обход получается функциональный, потому что мы получаем новый список, не меняя старый.
Может map обходить и несколько списков одновременно: можно применить map к нескольким спискам, тогда функция-аргумент будет применена ко всем первым элементам, затем ко всем вторым, и так далее. Но map потребует от входных списков иметь одинаковую длину, иначе вы получите ошибку.
Вот так можно поэлементно просуммировать три списка:
(map +
(list 1 2 3)
(list 10 20 30)
(list 100 200 300))
; '(111 222 333)Заметьте, не потребовалось даже использовать анонимную функцию, которая складывала бы три числа, ведь функция "+" принимает произвольное количество аргументов!
Задание
Реализуйте функцию maps, которая должна принимать два списка — список функций и список списков аргументов — и возвращать список результатов применения функций к наборам аргументов. Вот как использование maps должно выглядеть:
(maps
(list
inc
string?)
(list
(list 10 20)
(list "a" 0)))
; '((11 21) (true false))Здесь
'(11 21), это результат примененияincк(list 10 20)'(true false), это результат примененияstring?к(list "a" 0)
Полезное
Ваше упражнение проверяется по этим тестам
(ns loops-test
(:require [test-helper :refer [assert-solution]]
[index :refer [maps]]))
(assert-solution
[[(list) (list)]
[(list inc) (list (list 0))]
[(list inc string?) (list (list 0 100) (list "foo" 42))]]
[(list)
(list (list 1))
(list (list 1 101) (list true false))]
maps)Решение учителя откроется через:
20:00
