ЛЕКЦИЯ 5.
LET. ЦИКЛИЧЕСКИЕ ПРЕДЛОЖЕНИЯ
Содержание










5.1 L E T
В том случае, когда используется вычисление последовательности форм, удобно бывает ввести локальные переменные, сохраняемые до окончания вычислений. Это делается с помощью предложения LET.
В общем виде LET записывается
(LET ((var1 знач1) (var2 знач2)...) форма1 форма2 ... формаN)
LET вычисляется следующим образом:
1. Локальные переменные var1, var2, ...varM связываются одновременно со знач1, знач2, ..., значМ.
2. Вычисляются последовательно аргументы форма1, форма2, формаN.
3. В качестве значения предложения принимается значение последнего аргумента (неявный PROGN).
4. После выхода из предложения связи переменных var1, var2, ...varM ликвидируются.
Предложение LET удобно использовать, когда надо временно сохранять промежуточные значения.
Пример.
Рассмотрим функцию rectangle, которая имеет один аргумент - список из двух элементов, задающих длину и ширину прямоугольника. Функция рассчитывает и печатает площадь периметр прямоугольника.
| |
(defun rectangle (dim) (let ((len (car dim)) (wid (cadr dim))) (print (list 'area (* len wid))) (print (list 'perimeter (* (+ len wid) 2)))))) * (rectangle '(4 5)) |
Можно сначала рассчитать площадь, т.е. определить
| |
(defun rectangle (dim) (let ((len (car dim)) (wid (cadr dim)) (area (* len wid)) (print ( 'area area)) (print (list 'perimeter (* (+ len wid))))))) Обращение * (rectangle '(4 5))
|
Надо использовать предложение LET* , в котором значение переменных задается последовательно.
| |
(defun rectangle (dim) (let* ((len (car dim)) (wid (cadr dim)) (area (* len wid))) (print (list 'area area)) (print (list 'perimeter (* (+ len wid) 2))))))) |

5.2 Условный выход из функции: PROG RETURN
Встречаются ситуации, когда из тела функции, представленного последовательностью форм, требуется выйти, не доходя до последней формы. Это можно сделать используя предложения PROG RETURN, которые используются вместе.
| |
* (defun s-d () (prog (x y); локальные переменные (print '(type number)) (setq x (read)) (and (not (numberp x)) (return nil)) (print '(type number)) (setq y (read)) (and (not (numberp y)) (return nil)) (print (+ x y)) (print (- x y)))) * (s-d) (type number)8 (type number) (1) nil |
| |
* (s-d) (type number)8 (type number)1 9 7 nil |

| |
* (progn (print 1) (print 2) (print 3)) 123 |
| |
"string" |
| |
* "(+ 1 2)" "(+ 1 2)" |
| |
* (progn (setq x 4) (princ " x = ") (prin1 x) (princ " m ")) x = 4 m |
| |
* (progn (setq x 4) (princ "xxx ") (terpri) (princ "xox ")) xxx xox " xox" |



| |
1+2+3+4+ ... +N 1+2+3+4=10 * (add-integers 4) 10 (defun add-integers (last) (let (( count 1) (total 1)) (loop (cond (( equal count last) (return total))) (setq count (+ 1 count)) (setq total (+ total count))))) |
| |
Например, 3 x 4 это 3 + 3 + 3 + 3 = 12 * (int-multiply 3 4) 12 (defun int-multiply (x y) (let ((result 0)( count 0)) (loop (cond (( equal count y) (return result))) (setq count (+ 1 count)) (setq result (+ result x))))) |
| |
* (factorial 5) 120 1 x 2 x 3 x 4 x 5 = 120 (defun factorial ( num ) (let ((counter 0)( product 1)) (loop (cond (( equal counter num) (return product))) (setq counter (+ 1 counter)) (setq product (* counter product ))))) |
| |
( progn (setq x 0) (loop (if ( = 3 x) (return 't) (print x)) (setq x (+ 1 x)))) 0 1 2 t |
| |
* ( read-sum) Enter the next number: 15 Enter the next number: 30 Enter the next number: 45 Enter the next number: stop 90 (defun read-sum () (let ((input) (sum 0)) (loop (princ "Enter the next number:") (setq input (read)) (cond (( not (numberp input)) (return sum))) (setq sum (+ input sum))))) |

| |
* (double-list '(5 15 10 20)) (10 30 20 40) (defun double-list ( lis ) (let ((newlist nil)) (loop (cond (( null lis ) (return newlist))) (setq newlist (append newlist (list (* 2 (car lis))))) (setq lis (cdr lis ))))) |
| list | newlist | |
| Начальное состояние | (5 15 10 20) | () |
| итерация 1 | (15 10 20) | (10) |
| итерация 2 | (10 20) | (10 30) |
| итерация 1 | (20) | (10 30 20) |
| итерация 4 | () | (10 30 20 40) |
| результат | (10 30 20 40) |

| |
* ( do (( x 1 ( + 1 x))) (( > x 10) ( print 'end)) ( print x)) |
| |
(defun list-abs (lis) (let ((newlist nil)) (loop (cond (( null lis ) (return (reverse newlist)))) (setq newlist (cons (abs (car lis)) newlist)) (setq lis (cdr lis ))))) * (list-abs '(-1 2 -4 5)) |
| |
(defun list-abs (lis) (do ((oldlist lis (cdr oldlist)) (newlist nil (cons (abs (car oldlist)) newlist))) ((null oldlist) (reverse newlist))))) |
| |
* ( do (( x 1 (+ 1 x)) ( y 1 (+ 2 y)) ( z 3)); значение не меняется (( > x 10) ( print 'end)) (princ " x=") ( prin1 x) (princ " y=") ( prin1 y) (princ " z=") ( prin1 z) (terpri)) |
| |
* ( do (( x 1 (+ 1 x))) (( > x 10)) ( do (( y 1 (+ 2 y))) (( > y 4)) ( princ " x= ") ( prin1 x) ( princ " y= ") ( prin1 y) (terpri) )) |

| |
( defun appen-read () ( do (( x ( list ( read)) ( append x (list (read))))) (( equal (last x) '(end))); ???? '(end) (print x))) ( appen-read) |

| |
* (dotimes ( x 3 ) ( print x)) 0 - автоматически 1 2 t * (let ((x nil)) (dotimes (n 5 x) (setq x (cons n x)))) ( 4 3 2 1 0) |
