[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

symbol and variable

james

7/28/2015 6:16:00 AM

I am trying to understand lisp symbol, variable(lexical and dynamic) and please help to point whether my understanding is right.

CL-USER> (setq a 'hello)

; in: SETQ A
; (SETQ A 'HELLO)
;
; caught WARNING:
; undefined variable: A
;
; compilation unit finished
; Undefined variable:
; A
; caught 1 WARNING condition
HELLO

CL-USER> (symbol-name a)
"HELLO"

CL-USER> (set a 11)
11
CL-USER> (symbol-value a)
11

1>A is a variable, now it points a symbol 'hello, the symbol's name is hello and value is 1
2>A itself is a symbol too, its name is "A"

Lexical and dynamic is a way to decide how to got the variable by name
If a variable is not special ( here special means variable are defined by defvar/defparameter/ ((declare (special )), they will be find by lexical way( the nearest position will take effect). Or they will be find by dynamic way, you should use let to make the variable dynamic

For example
(defun foo-s ()
(declare (special *x*))
(+ *x* 1))

CL-USER> (let ((*x* 1)) (declare (special *x*)) (foo-s))
2

CL-USER> (defvar *x* 33)
*X*
CL-USER> (foo-s)
34

Anther question is about the declare (special), I know what the grammar here means but don't know the usage about this. When do we need (declare (special x)) ?

11 Answers

Barry Margolin

7/28/2015 2:25:00 PM

0

In article <e258ccba-cc2c-49dc-a42a-56d698deca32@googlegroups.com>,
james <dinglei2008@gmail.com> wrote:

> Anther question is about the declare (special), I know what the grammar here
> means but don't know the usage about this. When do we need (declare (special
> x)) ?

You need it if you haven't declared the variable globally special with
DEFVAR, and you want to access it as a dynamic variable within a
specific block of code.

This is relatively unusual.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Pascal J. Bourguignon

7/28/2015 2:53:00 PM

0

james <dinglei2008@gmail.com> writes:

> I am trying to understand lisp symbol, variable(lexical and dynamic)
> and please help to point whether my understanding is right.

Read article Message-ID: <873954cr4q.fsf@kuiper.lan.informatimago.com>
https://groups.google.c...!msg/comp.lang.lisp/4VyopdWcFI4/1sDQU-3H8VgJ
--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Kaz Kylheku

7/28/2015 3:28:00 PM

0

On 2015-07-28, james <dinglei2008@gmail.com> wrote:
> Lexical and dynamic is a way to decide how to got the variable by name
> If a variable is not special ( here special means variable are defined by
> defvar/defparameter/ ((declare (special )), they will be find by lexical way(
> the nearest position will take effect). Or they will be find by dynamic way,
> you should use let to make the variable dynamic

"Lexical" is a loaded word. You can have a lexical binding to a dynamic
variable. That is to say, some symbol X refers to a dynamic variable,
but this X is established in a lexical scope.

If you know C, there is a rough analogy which illustrates how the semantics
is separate from the syntax:

{
static int x;

}

The name x is scoped lexically, but the "storage class" is static: there
is one instance. The object named by x is not freshly instantiated on
entry into the scope.

In Lisp when we say "lexical" variable, we are usually tangling together the
syntax and semantics. We understand that it is tied to a syntactic scope in the
program, and semantically it is a freshly allocated variable on each entry into
the scope.

> For example
> (defun foo-s ()
> (declare (special *x*))
> (+ *x* 1))
>
> CL-USER> (let ((*x* 1)) (declare (special *x*)) (foo-s))
> 2
>
> CL-USER> (defvar *x* 33)
> *X*
> CL-USER> (foo-s)
> 34
>
> Anther question is about the declare (special), I know what the grammar here
> means but don't know the usage about this. When do we need
> (declare (special x)) ?

When you introduce x as a lexical binding in the variable namespace,
this (special x) declaration will alter the semantics of that binding.

The symbol x does now does not refer to a fresh location allocated when
evaluation of the scope begins. Rather, it denotes the dynamic variable x.

However, a temporary location is still allocated on entry into the scope,
and the dynamic variable is temporarily (over the evaluation of the block)
made turned into an alias for that location. This means that assignments
to the dynamic variable x in this scope are not permanent. The previous
value of the dynamic variable is restored when the scope terminates.

Lexical closures made inside this scope do not capture this hidden
temporary locations. If a lambda is created inside the scope, and the
scope terminates, the dynamic variable is restored nevertheless.
when the lambda is called and its body evaluates x, it just refers
to whatever value of the dynamic variable x that is current at the
time of the call.

All the above effects are informally called "dynamic scoping".

When we use defvar or defparameter, then the symbol is specially marked
("globally proclaimed special") so that all bindings of that symbol in any
scope use dynamic scoping, as if (declare (special ...)) were used.

(declare (special ...)) is used in situations when for some reason we don't
want to introduce this global marking on a symbol.

One example is inside some complicated macros: an uninterned symbol is obtained
from gensym, and used as a "secret" dynamic variable in the implementation of
the macro. It would be too heavy-handed to try to introduce a global (defvar
....) for that gensym or otherwise to make that symbol pervasively special. The
macro can simply generate the (declare (special ...)) in the right scope where
that is needed.

Another example, related to the above, occurs when some code wants to have
a "secret protocol" between two related functions: to pass a parameter from
one to the other that doesn't appear in the parameter list.

Suppose we have this:

(defun low-level-func ())

(defun intermediate-func ()
(low-level-func))

(defun high-level-func ()
(intermediate-func))

Suppose the intermediate levels are numerous and complicated. We want to add an
argument to low-level-func which is passed through from high-level-func without
changing all the intermediaries.

We could introduce a defvar. Bind it at the top level, access at the bottom:

(defvar *not-so-secret-param*)

(defun low-level-func ()
(do-something-with *not-so-secret-param*))

(defun intermediate-func ()
(low-level-func))

(defun high-level-func (param)
(let ((*not-so-secret-param* param))
(intermediate-func)))

With an explicit (declare (special ...)), we can be more sneaky:

(defun low-level-func ()
(do-something-with secret-param))

(defun intermediate-func ()
(low-level-func))

(defun high-level-func (param)
(let ((secret-param param))
(declare (special secret-param))
(intermediate-func)))

There is no longer any defvar. Moreover, we don't have to use *earmuffs* on the
variable. Why? Because we are not switching the secret-param symbol to
use special binding everywhere.

Inside low-level-func, there is no declaration. secret-param
is simply a free variable. If low-level-func is called directly,
and not via high-level-func, it contains an error: an undefined variable
is accessed. When called through high-level-func, it accesses the
definition set up by high-level-func.

(The behavior is the same with the defvar: defvar without an initial
value does not introduce a binding: the variable continues to be undefined.
It may be assigned, though.)

It is better to do the defvar approach: that way you clearly document
all the context-passing hacks in the code.

taruss

7/28/2015 11:31:00 PM

0

On Monday, July 27, 2015 at 11:16:26 PM UTC-7, james wrote:
> I am trying to understand lisp symbol, variable(lexical and dynamic) and
> please help to point whether my understanding is right.

Let me start with some preliminaries.

Symbols in lisp are a particular type of object. They have an independent existence are are used to name most of the items that you manipulate in a lisp program. For example, symbols are used to name classes, functions, types and variables among perhaps some other things I can't remember at the moment.

Symbols have their own independent existence.
Symbols have names which are strings.
Symbols also usually belong to a particular PACKAGE, which manages the namespace for mapping symbol names encountered by the reader to actual symbol objects. (FIND-SYMBOL also does this).

[There are some symbols that do not have packages, generally uninterned symbols which I won't go into here, but they are useful, typically in macros.]

It's important to get a grasp on the concept of a symbol object before venturing into the things that are named by symbols.

> CL-USER> (setq a 'hello)

SETQ, A and HELLO are all symbols.

You are assigning a value to the symbol A, but since A has not been defined as
a variable, either globally or via a binding construct such as LET or a lambda
ist, your lisp system will complain:

> ; in: SETQ A
> ; (SETQ A 'HELLO)
> ;
> ; caught WARNING:
> ; undefined variable: A
> ;
> ; compilation unit finished
> ; Undefined variable:
> ; A
> ; caught 1 WARNING condition
> HELLO

In spite of the complaint, almost all lisp systems will let you do this at top level without throwing an error. This is different from many other programming
languages where using undefined variables is a hard error.

>
> CL-USER> (symbol-name a)
> "HELLO"
>
> CL-USER> (set a 11)
> 11
> CL-USER> (symbol-value a)
> 11
>
> 1>A is a variable, now it points a symbol 'hello, the symbol's name is hello and value is 1
> 2>A itself is a symbol too, its name is "A"

Yes. This is all correct.


> Lexical and dynamic is a way to decide how to got the variable by name
> If a variable is not special ( here special means variable are defined by defvar/defparameter/ ((declare (special )), they will be find by lexical way( the nearest position will take effect). Or they will be find by dynamic way, you should use let to make the variable dynamic

I'm not completely clear on what you mean here.
Lexical and dynamic bindings affect how the lookup of variable values is
performed. For lexical binding, the binding of the variable that is used
is the variable binding that is lexically (by enclosing program text) visible
at the point the variable is used.

Dynamic scope means that the most recent binding that is established by the
program flow is used.

> For example
> (defun foo-s ()
> (declare (special *x*))
> (+ *x* 1))
>
> CL-USER> (let ((*x* 1)) (declare (special *x*)) (foo-s))
> 2
>
> CL-USER> (defvar *x* 33)
> *X*
> CL-USER> (foo-s)
> 34

Right. This is an example of dynamic binding.
Where *X* is used in FOO-S, there is no binding visible.
If, after the definition of FOO-S but before the DEFVAR, you had tried to call
(foo-s), then you would have had an unbound variable error, since there was
no dynamic binding of *X* in effect at that time.

Similarly, and again before the DEFVAR, if you had executed
(let ((*x* 1)) (foo-s))
without the special declaration, then you would have also had an unbound
because the LET would only create a lexical binding of *X*.
Once you had globally declared *X* to be special by using DEFVAR, you would
be able to use the form above and have it work, because after DEFVAR, *X* is
globally special, and thus the LET form would create a dynamic binding.

>
> Anther question is about the declare (special), I know what the grammar here
> means but don't know the usage about this. When do we need
> (declare (special x)) ?

As Barry said, you need this whenever you want a dynamic binding for a variable
that is not globally special. This is somewhat rare, but it can be used
(abused?) to allow communication by dynamic binding across levels of function
calls without the need to pass or otherwise manipulate the variable. So one
could do the following [without any representation that this is good style]:

(defun get-values ()
(let ((*accumulator* nil))
(declare (special *accumulator*))
(a)
(m)
(x)
(reverse *accumulator*)))

(defun a ()
;; Would really do some stuff and pass it to B.
(b))
(defun b ()
;; etc.
(c))
(defun c ()
(declare (special *accumulator*))
(push 'c *accumulator*))

(defun m ()
(n))
(defun n ()
(declare (special *accumulator*))
(push 'en *accumulator*))

(defun x ()
(y)
(z))
(defun y ()
(declare (special *accumulator*))
(push 'why *accumulator*))
(defun z ()
(declare (special *accumulator*))
(push 'z *accumulator*))

(get-values) => (C EN WHY Z)

And at the end:
(boundp '*ACCUMULATOR*) => NIL

so you can't get at the value here. Even if you were to use DEFVAR, the
binding of *ACCUMULATOR* in GET-VALUES will stop the value from being available
once that function returns.


The main advantage of using non-global special variables for this is that you
will then get an error if you try to invoke one of the functions that expects
to be called in an environment where that variable exists without establishing
the requisite binding. But this can be fragile and obscures the data input and
output behavior and can make the program much harder to understand.

james

7/29/2015 3:43:00 AM

0

On Tuesday, July 28, 2015 at 10:25:29 PM UTC+8, Barry Margolin wrote:
> In article <e258ccba-cc2c-49dc-a42a-56d698deca32@googlegroups.com>,
> james <dinglei2008@gmail.com> wrote:
>
> > Anther question is about the declare (special), I know what the grammar here
> > means but don't know the usage about this. When do we need (declare (special
> > x)) ?
>
> You need it if you haven't declared the variable globally special with
> DEFVAR, and you want to access it as a dynamic variable within a
> specific block of code.
>
> This is relatively unusual.
>
> --
> Barry Margolin, barmar@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***

Thanks, Now I will think as this is a grammar suger which not seen in python or java :)

james

7/29/2015 3:44:00 AM

0

On Tuesday, July 28, 2015 at 10:52:38 PM UTC+8, informatimago wrote:
> james <dinglei2008@gmail.com> writes:
>
> > I am trying to understand lisp symbol, variable(lexical and dynamic)
> > and please help to point whether my understanding is right.
>
> Read article Message-ID: <873954cr4q.fsf@kuiper.lan.informatimago.com>
> https://groups.google.c...!msg/comp.lang.lisp/4VyopdWcFI4/1sDQU-3H8VgJ
> --
> __Pascal Bourguignon__ http://www.informat...
> "The factory of the future will have only two employees, a man and a
> dog. The man will be there to feed the dog. The dog will be there to
> keep the man from touching the equipment." -- Carl Bass CEO Autodesk

Thanks to point this.

james

7/29/2015 3:47:00 AM

0

On Wednesday, July 29, 2015 at 7:31:33 AM UTC+8, tar...@google.com wrote:
> On Monday, July 27, 2015 at 11:16:26 PM UTC-7, james wrote:
> > I am trying to understand lisp symbol, variable(lexical and dynamic) and
> > please help to point whether my understanding is right.
>
> Let me start with some preliminaries.
>
> Symbols in lisp are a particular type of object. They have an independent existence are are used to name most of the items that you manipulate in a lisp program. For example, symbols are used to name classes, functions, types and variables among perhaps some other things I can't remember at the moment.
>
> Symbols have their own independent existence.
> Symbols have names which are strings.
> Symbols also usually belong to a particular PACKAGE, which manages the namespace for mapping symbol names encountered by the reader to actual symbol objects. (FIND-SYMBOL also does this).
>
> [There are some symbols that do not have packages, generally uninterned symbols which I won't go into here, but they are useful, typically in macros..]
>
> It's important to get a grasp on the concept of a symbol object before venturing into the things that are named by symbols.
>
> > CL-USER> (setq a 'hello)
>
> SETQ, A and HELLO are all symbols.
>
> You are assigning a value to the symbol A, but since A has not been defined as
> a variable, either globally or via a binding construct such as LET or a lambda
> ist, your lisp system will complain:
>
> > ; in: SETQ A
> > ; (SETQ A 'HELLO)
> > ;
> > ; caught WARNING:
> > ; undefined variable: A
> > ;
> > ; compilation unit finished
> > ; Undefined variable:
> > ; A
> > ; caught 1 WARNING condition
> > HELLO
>
> In spite of the complaint, almost all lisp systems will let you do this at top level without throwing an error. This is different from many other programming
> languages where using undefined variables is a hard error.
>
> >
> > CL-USER> (symbol-name a)
> > "HELLO"
> >
> > CL-USER> (set a 11)
> > 11
> > CL-USER> (symbol-value a)
> > 11
> >
> > 1>A is a variable, now it points a symbol 'hello, the symbol's name is hello and value is 1
> > 2>A itself is a symbol too, its name is "A"
>
> Yes. This is all correct.
>
>
> > Lexical and dynamic is a way to decide how to got the variable by name
> > If a variable is not special ( here special means variable are defined by defvar/defparameter/ ((declare (special )), they will be find by lexical way( the nearest position will take effect). Or they will be find by dynamic way, you should use let to make the variable dynamic
>
> I'm not completely clear on what you mean here.
> Lexical and dynamic bindings affect how the lookup of variable values is
> performed. For lexical binding, the binding of the variable that is used
> is the variable binding that is lexically (by enclosing program text) visible
> at the point the variable is used.
>
> Dynamic scope means that the most recent binding that is established by the
> program flow is used.
>
> > For example
> > (defun foo-s ()
> > (declare (special *x*))
> > (+ *x* 1))
> >
> > CL-USER> (let ((*x* 1)) (declare (special *x*)) (foo-s))
> > 2
> >
> > CL-USER> (defvar *x* 33)
> > *X*
> > CL-USER> (foo-s)
> > 34
>
> Right. This is an example of dynamic binding.
> Where *X* is used in FOO-S, there is no binding visible.
> If, after the definition of FOO-S but before the DEFVAR, you had tried to call
> (foo-s), then you would have had an unbound variable error, since there was
> no dynamic binding of *X* in effect at that time.
>
> Similarly, and again before the DEFVAR, if you had executed
> (let ((*x* 1)) (foo-s))
> without the special declaration, then you would have also had an unbound
> because the LET would only create a lexical binding of *X*.
> Once you had globally declared *X* to be special by using DEFVAR, you would
> be able to use the form above and have it work, because after DEFVAR, *X* is
> globally special, and thus the LET form would create a dynamic binding.
>
> >
> > Anther question is about the declare (special), I know what the grammar here
> > means but don't know the usage about this. When do we need
> > (declare (special x)) ?
>
> As Barry said, you need this whenever you want a dynamic binding for a variable
> that is not globally special. This is somewhat rare, but it can be used
> (abused?) to allow communication by dynamic binding across levels of function
> calls without the need to pass or otherwise manipulate the variable. So one
> could do the following [without any representation that this is good style]:
>
> (defun get-values ()
> (let ((*accumulator* nil))
> (declare (special *accumulator*))
> (a)
> (m)
> (x)
> (reverse *accumulator*)))
>
> (defun a ()
> ;; Would really do some stuff and pass it to B.
> (b))
> (defun b ()
> ;; etc.
> (c))
> (defun c ()
> (declare (special *accumulator*))
> (push 'c *accumulator*))
>
> (defun m ()
> (n))
> (defun n ()
> (declare (special *accumulator*))
> (push 'en *accumulator*))
>
> (defun x ()
> (y)
> (z))
> (defun y ()
> (declare (special *accumulator*))
> (push 'why *accumulator*))
> (defun z ()
> (declare (special *accumulator*))
> (push 'z *accumulator*))
>
> (get-values) => (C EN WHY Z)
>
> And at the end:
> (boundp '*ACCUMULATOR*) => NIL
>
> so you can't get at the value here. Even if you were to use DEFVAR, the
> binding of *ACCUMULATOR* in GET-VALUES will stop the value from being available
> once that function returns.
>
>
> The main advantage of using non-global special variables for this is that you
> will then get an error if you try to invoke one of the functions that expects
> to be called in an environment where that variable exists without establishing
> the requisite binding. But this can be fragile and obscures the data input and
> output behavior and can make the program much harder to understand.

Thanks, Variable and symbol is hard to understand for a lisper rookie but interesting.

Pascal J. Bourguignon

7/29/2015 4:36:00 AM

0

james <dinglei2008@gmail.com> writes:

> On Tuesday, July 28, 2015 at 10:25:29 PM UTC+8, Barry Margolin wrote:
>> In article <e258ccba-cc2c-49dc-a42a-56d698deca32@googlegroups.com>,
>> james <dinglei2008@gmail.com> wrote:
>>
>> > Anther question is about the declare (special), I know what the grammar here
>> > means but don't know the usage about this. When do we need (declare (special
>> > x)) ?
>>
>> You need it if you haven't declared the variable globally special with
>> DEFVAR, and you want to access it as a dynamic variable within a
>> specific block of code.
>>
>> This is relatively unusual.
>>
>> --
>> Barry Margolin, barmar@alum.mit.edu
>> Arlington, MA
>> *** PLEASE post questions in newsgroups, not directly to me ***
>
> Thanks, Now I will think as this is a grammar suger which not seen in python or java :)

It is explained in the url I gave you precedently. Why didn't you read it?
https://groups.google.c...!msg/comp.lang.lisp/4VyopdWcFI4/1sDQU-3H8VgJ
What use is there to answer you if you don't read those answers?

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

james

7/29/2015 5:56:00 AM

0

On Wednesday, July 29, 2015 at 12:35:47 PM UTC+8, informatimago wrote:
> james <dinglei2008@gmail.com> writes:
>
> > On Tuesday, July 28, 2015 at 10:25:29 PM UTC+8, Barry Margolin wrote:
> >> In article <e258ccba-cc2c-49dc-a42a-56d698deca32@googlegroups.com>,
> >> james <dinglei2008@gmail.com> wrote:
> >>
> >> > Anther question is about the declare (special), I know what the grammar here
> >> > means but don't know the usage about this. When do we need (declare (special
> >> > x)) ?
> >>
> >> You need it if you haven't declared the variable globally special with
> >> DEFVAR, and you want to access it as a dynamic variable within a
> >> specific block of code.
> >>
> >> This is relatively unusual.
> >>
> >> --
> >> Barry Margolin, barmar@alum.mit.edu
> >> Arlington, MA
> >> *** PLEASE post questions in newsgroups, not directly to me ***
> >
> > Thanks, Now I will think as this is a grammar suger which not seen in python or java :)
>
> It is explained in the url I gave you precedently. Why didn't you read it?
> https://groups.google.c...!msg/comp.lang.lisp/4VyopdWcFI4/1sDQU-3H8VgJ
> What use is there to answer you if you don't read those answers?
>
> --
> __Pascal Bourguignon__ http://www.informat...
> "The factory of the future will have only two employees, a man and a
> dog. The man will be there to feed the dog. The dog will be there to
> keep the man from touching the equipment." -- Carl Bass CEO Autodesk

I read link and it's very helpful. Maybe my expression here is not fit.

taruss

7/29/2015 4:47:00 PM

0

On Tuesday, July 28, 2015 at 8:46:47 PM UTC-7, james wrote:

> Thanks, Variable and symbol is hard to understand for a lisper rookie but interesting.

Perhaps this is more confusing in lisp is because most other programming
languages don't have a first-class object that is a "symbol" or "identifier".
Typically, only the compiler deals directly with the identifiers in, say, a
C program.

In other words, in something like:
int x;
x = 5;
the users doesn't deal with an identifier object named "x", only the compiler deals with the identifier "x". User code only uses the variable named by the
identifier "x".

In Lisp, both the identifier (called a symbol) and the variable are available
to the user code, so it comes to the attention of the user rather than just
being something compiler writers care about.