Scheme/Tutorial/6

Материал из ALT Linux Wiki

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))
   .....