Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Practical Common Lisp: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

(let ((x 10) (y 20) z)

... )

When the LET form is evaluated, all the initial value forms are first evaluated. Then new bindings are created and initialized to the appropriate initial values before the body forms are executed. Within the body of the LET , the variable names refer to the newly created bindings. After the LET , the names refer to whatever, if anything, they referred to before the LET .

The value of the last expression in the body is returned as the value of the LET expression. Like function parameters, variables introduced with LET are rebound each time the LET is entered. [72] The variables in LET forms and function parameters are created by exactly the same mechanism. In fact, in some Lisp dialects—though not Common Lisp— LET is simply a macro that expands into a call to an anonymous function. That is, in those dialects, the following: (let ((x 10)) (format t "~a" x)) is a macro form that expands into this: ((lambda (x) (format t "~a" x)) 10)

The scope of function parameters and LET variables—the area of the program where the variable name can be used to refer to the variable's binding—is delimited by the form that introduces the variable. This form—the function definition or the LET —is called the binding form . As you'll see in a bit, the two types of variables—lexical and dynamic—use two slightly different scoping mechanisms, but in both cases the scope is delimited by the binding form.

If you nest binding forms that introduce variables with the same name, then the bindings of the innermost variable shadows the outer bindings. For instance, when the following function is called, a binding is created for the parameter xto hold the function's argument. Then the first LET creates a new binding with the initial value 2, and the inner LET creates yet another binding, this one with the initial value 3. The bars on the right mark the scope of each binding.

(defun foo (x)

(format t "Parameter: ~a~%" x) ; |<���——— x is argument

(let ((x 2)) ; |

(format t "Outer LET: ~a~%" x) ; | |<���—— x is 2

(let ((x 3)) ; | |

(format t "Inner LET: ~a~%" x)) ; | | |<���— x is 3

(format t "Outer LET: ~a~%" x)) ; | |

(format t "Parameter: ~a~%" x)) ; |

Each reference to xwill refer to the binding with the smallest enclosing scope. Once control leaves the scope of one binding form, the binding from the immediately enclosing scope is unshadowed and xrefers to it instead. Thus, calling fooresults in this output:

CL-USER> (foo 1)

Parameter: 1

Outer LET: 2

Inner LET: 3

Outer LET: 2

Parameter: 1

NIL

In future chapters I'll discuss other constructs that also serve as binding forms—any construct that introduces a new variable name that's usable only within the construct is a binding form.

For instance, in Chapter 7 you'll meet the DOTIMES loop, a basic counting loop. It introduces a variable that holds the value of a counter that's incremented each time through the loop. The following loop, for example, which prints the numbers from 0 to 9, binds the variable x:

(dotimes (x 10) (format t "~d " x))

Another binding form is a variant of LET , LET* . The difference is that in a LET , the variable names can be used only in the body of the LET —the part of the LET after the variables list—but in a LET* , the initial value forms for each variable can refer to variables introduced earlier in the variables list. Thus, you can write the following:

(let* ((x 10)

(y (+ x 10)))

(list x y))

but not this:

(let ((x 10)

(y (+ x 10)))

(list x y))

However, you could achieve the same result with nested LET s.

(let ((x 10))

(let ((y (+ x 10)))

(list x y)))

Lexical Variables and Closures

By default all binding forms in Common Lisp introduce lexically scoped variables. Lexically scoped variables can be referred to only by code that's textually within the binding form. Lexical scoping should be familiar to anyone who has programmed in Java, C, Perl, or Python since they all provide lexically scoped "local" variables. For that matter, Algol programmers should also feel right at home, as Algol first introduced lexical scoping in the 1960s.

However, Common Lisp's lexical variables are lexical variables with a twist, at least compared to the original Algol model. The twist is provided by the combination of lexical scoping with nested functions. By the rules of lexical scoping, only code textually within the binding form can refer to a lexical variable. But what happens when an anonymous function contains a reference to a lexical variable from an enclosing scope? For instance, in this expression:

(let ((count 0)) #'(lambda () (setf count (1+ count))))

the reference to countinside the LAMBDA form should be legal according to the rules of lexical scoping. Yet the anonymous function containing the reference will be returned as the value of the LET form and can be invoked, via FUNCALL , by code that's not in the scope of the LET . So what happens? As it turns out, when countis a lexical variable, it just works. The binding of countcreated when the flow of control entered the LET form will stick around for as long as needed, in this case for as long as someone holds onto a reference to the function object returned by the LET form. The anonymous function is called a closure because it "closes over" the binding created by the LET .

The key thing to understand about closures is that it's the binding, not the value of the variable, that's captured. Thus, a closure can not only access the value of the variables it closes over but can also assign new values that will persist between calls to the closure. For instance, you can capture the closure created by the previous expression in a global variable like this:

(defparameter *fn* (let ((count 0)) #'(lambda () (setf count (1+ count)))))

Then each time you invoke it, the value of count will increase by one.

CL-USER> (funcall *fn*)

1

CL-USER> (funcall *fn*)

2

CL-USER> (funcall *fn*)

3

A single closure can close over many variable bindings simply by referring to them. Or multiple closures can capture the same binding. For instance, the following expression returns a list of three closures, one that increments the value of the closed over countbinding, one that decrements it, and one that returns the current value:

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x