Изучаю сейчас сабж, и у меня возникли некоторые затруднения. Предположим, передо мной стоит простая задача: реализовать операции добавления числа и умножения на число некой последовательности чисел. Как это грамотно сделать с точки зрения функционального программирования?
В sicp предлагается вариант некого подобия ОО, это бы выглядело так:
(define make-sequence
(lambda (values-list)
(lambda (message)
(cond
((equal? message 'add)
(lambda (number)
(make-sequence
(map (lambda (value) (+ value number))
values-list))))
((equal? message 'scale)
(lambda (number)
(make-sequence
(map (lambda (value) (* value number))
values-list))))
(else
(display "Wrong message for make-sequence"))))))
И потом использование:
(define s (make-sequence (list 0 1 2 3)))
((s 'add) 4)
((s 'scale) 2)
Но, что-то, меня смущает эта псевдо-диспетчеризация :) А если мне надо будет миллион раз вызвать (s 'add), он ведь будет миллион раз делать cond, хотя я же явно ему указываю, что я хочу.
С другой стороны, мне явно надо определять нужные операции внутри make-sequence, чтобы получить замыкание, иначе придется все параметры передавать еще куда-то дальше, а если их не один, а десять, это тоже накладно :(
Сходу я придумал такой вариант, с возвращением списка замыканий:
(define make-sequence
(lambda (values-list)
(list
(lambda (number)
(make-sequence
(map (lambda (value) (+ value number))
values-list)))
(lambda (number)
(make-sequence
(map (lambda (value) (* value number))
values-list))))))
(define sequence-add
(lambda (sequence number)
((car sequence) number)))
(define sequence-scale
(lambda (sequence number)
((cadr sequence) number)))
И использование:
(define s (make-sequence (list 0 1 2 3)))
(sequence-add s 4)
(sequence-scale s 2)
Тут много можно под макросы упаковать, но для наглядности я оставил так. Сразу видны минусы: чтобы выполнить операцию, надо ползти по списку, что тоже должно быть накладно :(
Есть какая-нибудь устоявшаяся практика в реализации таких вещей?