james
7/29/2015 3:47:00 AM
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.