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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

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

Интервал:

Закладка:

Сделать

(stuff))

In any code that runs as a result of the call to stuff, references to *standard-output*will use the binding established by the LET . And when stuffreturns and control leaves the LET , the new binding of *standard-output*will go away and subsequent references to *standard-output*will see the binding that was current before the LET . At any given time, the most recently established binding shadows all other bindings. Conceptually, each new binding for a given dynamic variable is pushed onto a stack of bindings for that variable, and references to the variable always use the most recent binding. As binding forms return, the bindings they created are popped off the stack, exposing previous bindings. [77] Though the standard doesn't specify how to incorporate multithreading into Common Lisp, implementations that provide multithreading follow the practice established on the Lisp machines and create dynamic bindings on a per-thread basis. A reference to a global variable will find the binding most recently established in the current thread, or the global binding.

A simple example shows how this works.

(defvar *x* 10)

(defun foo () (format t "X: ~d~%" *x*))

The DEFVAR creates a global binding for the variable *x*with the value 10. The reference to *x*in foowill look up the current binding dynamically. If you call foofrom the top level, the global binding created by the DEFVAR is the only binding available, so it prints 10.

CL-USER> (foo)

X: 10

NIL

But you can use LET to create a new binding that temporarily shadows the global binding, and foowill print a different value.

CL-USER> (let ((*x* 20)) (foo))

X: 20

NIL

Now call fooagain, with no LET , and it again sees the global binding.

CL-USER> (foo)

X: 10

NIL

Now define another function.

(defun bar ()

(foo)

(let ((*x* 20)) (foo))

(foo))

Note that the middle call to foois wrapped in a LET that binds *x*to the new value 20. When you run bar, you get this result:

CL-USER> (bar)

X: 10

X: 20

X: 10

NIL

As you can see, the first call to foosees the global binding, with its value of 10. The middle call, however, sees the new binding, with the value 20. But after the LET , fooonce again sees the global binding.

As with lexical bindings, assigning a new value affects only the current binding. To see this, you can redefine footo include an assignment to *x*.

(defun foo ()

(format t "Before assignment~18tX: ~d~%" *x*)

(setf *x* (+ 1 *x*))

(format t "After assignment~18tX: ~d~%" *x*))

Now fooprints the value of *x*, increments it, and prints it again. If you just run foo, you'll see this:

CL-USER> (foo)

Before assignment X: 10

After assignment X: 11

NIL

Not too surprising. Now run bar.

CL-USER> (bar)

Before assignment X: 11

After assignment X: 12

Before assignment X: 20

After assignment X: 21

Before assignment X: 12

After assignment X: 13

NIL

Notice that *x*started at 11—the earlier call to fooreally did change the global value. The first call to foofrom barincrements the global binding to 12. The middle call doesn't see the global binding because of the LET . Then the last call can see the global binding again and increments it from 12 to 13.

So how does this work? How does LET know that when it binds *x*it's supposed to create a dynamic binding rather than a normal lexical binding? It knows because the name has been declared special . [78] This is why dynamic variables are also sometimes called special variables . The name of every variable defined with DEFVAR and DEFPARAMETER is automatically declared globally special. This means whenever you use such a name in a binding form—in a LET or as a function parameter or any other construct that creates a new variable binding—the binding that's created will be a dynamic binding. This is why the *naming* *convention*is so important—it'd be bad news if you used a name for what you thought was a lexical variable and that variable happened to be globally special. On the one hand, code you call could change the value of the binding out from under you; on the other, you might be shadowing a binding established by code higher up on the stack. If you always name global variables according to the *naming convention, you'll never accidentally use a dynamic binding where you intend to establish a lexical binding.

It's also possible to declare a name locally special. If, in a binding form, you declare a name special, then the binding created for that variable will be dynamic rather than lexical. Other code can locally declare a name special in order to refer to the dynamic binding. However, locally special variables are relatively rare, so you needn't worry about them. [79] If you must know, you can look up DECLARE , SPECIAL , and LOCALLY in the HyperSpec.

Dynamic bindings make global variables much more manageable, but it's important to notice they still allow action at a distance. Binding a global variable has two at a distance effects—it can change the behavior of downstream code, and it also opens the possibility that downstream code will assign a new value to a binding established higher up on the stack. You should use dynamic variables only when you need to take advantage of one or both of these characteristics.

Constants

One other kind of variable I haven't mentioned at all is the oxymoronic "constant variable." All constants are global and are defined with DEFCONSTANT . The basic form of DEFCONSTANT is like DEFPARAMETER .

(defconstant name initial-value-form [ documentation-string ])

As with DEFVAR and DEFPARAMETER , DEFCONSTANT has a global effect on the name used—thereafter the name can be used only to refer to the constant; it can't be used as a function parameter or rebound with any other binding form. Thus, many Lisp programmers follow a naming convention of using names starting and ending with +for constants. This convention is somewhat less universally followed than the *-naming convention for globally special names but is a good idea for the same reason. [80] Several key constants defined by the language itself don't follow this convention—not least of which are T and NIL . This is occasionally annoying when one wants to use t as a local variable name. Another is PI , which holds the best long-float approximation of the mathematical constant pi.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x