
2.2. Иерархические данные и свойство замыкания
113
Мы можем выделить здесь общую идею и зафиксировать ее как схему, выраженную
в виде процедуры высшего порядка, в точности как в разделе 1.3. Здесь эта процедура
высшего порядка называе тся map. Map берет в качестве аргументов процедуру от од-
ного аргумента и список, а возвращает список результатов, полученн ых применением
процедуры к каждому элементу списка
12
:
(define (map proc items)
(if (null? items)
nil
(cons (proc (car items))
(map proc (cdr items)))))
(map abs (list -10 2.5 -11.6 17))
(10 2.5 11.6 17)
(map (lambda (x) (* x x))
(list 1 2 3 4))
(1 4 9 16)
Теперь мы можем дать новое определение scale-list через map:
(define (scale-list items factor)
(map (lambda (x) (* x factor))
items))
Map является важным конструктом, не только потому, что она фиксирует общую
схему, но и потому, что она повышает уровень абстракции при работе со списками. В
исходном определении scale-list рекур сивная структура программы привлекает вни-
мание к поэлементной обработке списка. Определение scale-list через map устраня-
ет этот уровень деталей и подчерки вает, что умножение преобразует список элементов
в список результатов. Разница между этими двумя определени ями состоит не в том,
что компьютер выполняет другой процесс (это не так), а в том, что м ы думаем об этом
процессе по-другому. В сущности, map помогает установить барьер абстракции, который
отделяет реализацию процедур, преобразующих списки, от деталей того, как выбираются
и комбинируются элементы списков. Подобно барьерам на рисунке 2.1, эта абстракция
позволяет нам свободно изменять низкоуровневые детали того, как реализованы списки,
сохраняя концептуальную схему с операциями, переводящими одни последовательности
12
Стандартная Scheme содержит более общую процедуру map, чем описанная здесь. Этот вариант map
принимает процедуру от n аргументов и n списков и применяет процедуру ко всем первым элементам списков,
всем вторым элементам списков и так далее. Возвращается список результатов. Например:
(map + (list 1 2 3) (list 40 50 60) (list 700 800 900))
(741 852 963)
(map (lambda (x y) (+ x (* 2 y)))
(list 1 2 3)
(list 4 5 6))
(9 12 15)