Scheme/Tutorial/6
12 локальные переменные (продолжение)
Продолжаем неустанно совершенствоваться в Scheme. Вы уже видели в предыдущий раз, что локальные переменные можно объявлять в теле функции, пользуясь тем же самым define
(define (func) (define a 5) (+ a 3))
Однако есть ещё несколько интересных и полезных приёмов работы. Воспользуемся тем, что параметры функции по сути те же локальные переменные. Тогда пример выше, можно было бы сделать следующим образом:
(define (func) ((lambda (a) (+ a 3)) 5))
Попробуем понять что же произошло. Мы создали функцию с параметром, который назвали 'a', поместили в неё всё что нам необходимо, и после этого запустили её придав параметру требуемое значение '5'. Всё ,как говорится , гениально и просто. Попробуем ещё, вместо:
(define x 5) (define y 6) (write x) (+ x (* x y))
мы можем написать:
((lambda (x y) (write x) (+ x (* x y))) 5 6)
Данный приём настолько популярен, что имеет общепринятое сокращение - let. Приведённые выражения в сокращённом виде записываются так:
(define (func) (let ((a 5)) (+ a 3)))
(let ((x 5) (y 6)) (write x) (+ x (* x y)))
Если немного поразмышлять, то мы получили не просто способ объявления локальных переменных, а возможность делать блоки с локальными переменными в произвольном месте кода, например:
(define a 3) (write a) ; будет напечатано 3 (let ((a 5)) (write a)) ; будет напечатано 5 (write a) ; будет напечатано 3
У этого приёма есть один существенный недостаток, поскольку формальные параметры инициализируются независимо друг от друга и в неопределённом порядке, мы не можем использовать одни из них для инициализации других, например в примере с двумя параметрами нельзя у задать равным x. Но против лома всегда есть другой лом. Применим одну маленькую хитрость - будем связывать переменные по очереди:
(let ((x 3)) (let ((y x)) .....
Тогда всё получится, на момент определения 'y', 'x' уже известен и проинициализирован. Этот приём тоже очень распространён, а потому тоже имеет общепринятое сокращение - let*.
(let* ((x 3) (y x)) .....