Peter Siebel - Practical Common Lisp
Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.
- Название:Practical Common Lisp
- Автор:
- Издательство:Apress
- Жанр:
- Год:2005
- ISBN:1-59059-239-5
- Рейтинг книги:4 / 5. Голосов: 1
-
Избранное:Добавить в избранное
- Отзывы:
-
Ваша оценка:
- 80
- 1
- 2
- 3
- 4
- 5
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 stuff
returns 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 foo
will look up the current binding dynamically. If you call foo
from 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 foo
will print a different value.
CL-USER> (let ((*x* 20)) (foo))
X: 20
NIL
Now call foo
again, 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 foo
is 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 foo
sees the global binding, with its value of 10. The middle call, however, sees the new binding, with the value 20. But after the LET
, foo
once again sees the global binding.
As with lexical bindings, assigning a new value affects only the current binding. To see this, you can redefine foo
to 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 foo
prints 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 foo
really did change the global value. The first call to foo
from bar
increments 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» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.