Scheme/Tutorial/6

Материал из ALT Linux Wiki
< Scheme‎ | Tutorial
Версия от 13:14, 11 мая 2012; MichaelShigorin (обсуждение | вклад) (вычитка)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)

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

далее>>