--
Who's your mama ?
CLTL2 talks about `variable-information'. SBCL provides it via the sb-
cltl2 package:
(defmacro lexically-bound-p (variable &environment env)
(eq :lexical (sb-cltl2:variable-information variable env)))
SW> (let ((x 42))
(if (lexically-bound-p x)
(format t "X is here, and its value is ~A~%" x)
(write-line "X is not here")))
X is here, and its value is 42
NIL
SW> (let ((y 42))
(if (lexically-bound-p x)
(format t "X is here, and its value is ~A~%" x)
(write-line "X is not here")))
X is not here
"X is not here"
SW>
> Is there a way to find out if a symbol has a binding in the lexical
> environment ? Ideally something equivalent to boundp but working for
> lexical variables.
Not portably.
--
__Pascal Bourguignon__
In an ANSI-conformant way *within* the CLHS? Not that I know of.
But you can always use one of the flavors of "environments access"
extensions, such as the one Franz proposed:
http://www.franz.com/support/documentation/7.0/doc/environments.htm
http://www.franz.com/support/documentation/7.0/doc/operators/system/variable-information.htm
And each implementation of course has *some* way to get at the information.
In CMUCL, you might do it this way:
> (defmacro boundp/lexical (form &environment env)
;; Cribbed from "src/code/eval.lisp" DEFUN MACROEXPAND-1
(and (symbolp form)
(let* ((venv (when env (c::lexenv-variables env)))
(local-def (cdr (assoc form venv))))
(cond
((and (consp local-def)
(eq (car local-def) 'system:macro))
:symbol-macrolet)
((eq (type-of local-def) 'c::lambda-var)
:lexical-variable)
((null local-def)
nil)
(t (error "Unknown type: ~s" form))))))
BOUNDP/LEXICAL
> (boundp/lexical x)
NIL
> (let ((x 123))
(declare (ignorable x))
(boundp/lexical x))
:LEXICAL-VARIABLE
> (let ((x 123))
(declare (ignorable x)) ; Stifle "never used" complaint
(symbol-macrolet ((y 456))
(let ((z 789))
(declare (ignorable y)) ; (ditto)
(list (boundp/lexical w)
(boundp/lexical x)
(boundp/lexical y)
(boundp/lexical z)))))
(NIL :LEXICAL-VARIABLE :SYMBOL-MACROLET :LEXICAL-VARIABLE)
>
-Rob
-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
This is not equivalent to boundp (as the OP asked): boundp is a
function taking an arbitrary symbol; your test is completely static,
as the symbol is determined at compile-time.
Lexical variable information is not guaranteed to be still around at
runtime, so what the OP wants is not doable portably, and even within
a single implementation it might be doable only with certain debug/
speed settings or only in interpreted code. Thus, it's probably the
wrong solution to the problem, whatever the problem is.
Alessio
That's interesting, but why are you telling me this? I'm sure the OP
will understand exactly how I interpreted his question based on the
code example I posted -- and what he really wants will reveal itself
soon based (perhaps) on this.
If you want to post some code to cover the (many, and interesting, I'm
sure) other possible interpretations of what the OP meant I see no
reason to stop you or interrupt you.
PS: I have used `variable-information' on numerous occasions. It is
quite clearly specified in CLTL2.
It is not an equivalent, but it is an analog which is as close as it can be.
Special variables and lexical variables are different, hence constructs
which check their presence must be different and they must reflect
that difference.
Special variables have indefinite scope and dynamic extent.
This means that boundp-for-special-variable should do a check in runtime
and it should accept any symbol.
Lexical variables have lexical scope and indefinite extent.
Therefore, boundp-for-lexical-variable should work statically, at compile
time, because that information is available at compilte time, and perhaps
*only* at compile time.
So if we assume that OP knows what lexical variables are, answer
which Lars gave was a correct answer.
Of course, there is a chance that OP does not really understand how
lexical variables work, but why should we assume ignorance of a poster
if he gave us no reasons to?
> Is there a way to find out if a symbol has a binding in the lexical
> environment ? Ideally something equivalent to boundp but working for
> lexical variables.
Lexical variables are not symbols. And so boundp would make no sense.
The compiler is free to optimize away the variable entirely during
compilations. Allocating it in a register on on the stack.
That said compilers (with optimize debug > 0) will contain some data on
lexical data, but this is compiler dependent.
Normally if you get a warning when compiling the function: 'variable
<whatever> assumed special' it means you misspelled a variable name on
reference.
see CLHS: symbols and packages (CH 11)
--
John Thingstad
> Of course, there is a chance that OP does not really understand how
> lexical variables work, but why should we assume ignorance of a poster
> if he gave us no reasons to?
Because lexical variables are never bound at all. They are declared or
they are undeclared. You can check if a lexical variable is DECLARED at
compile time.
Dynamic variables are symbols. Symbols are only guaranteed to contain a
name. This allows the remaining slots to exist in a unbound state that is
unique to dynamic variables.
--
John Thingstad
>
> Lexical variables are not symbols. And so boundp would make no sense.
> The compiler is free to optimize away the variable entirely during
> compilations. Allocating it in a register on on the stack. That said
> compilers (with optimize debug > 0) will contain some data on lexical
> data, but this is compiler dependent.
Correction: The reader creates a symbol when a lexical vaiable is read.
It is however not put in the *package* table. In stead it is put in a
lexical-environment.
--
John Thingstad
I think you are confused. There is no such thing as "the *package*
table", and the idea of "reading a lexical variable" is non-sensical.
Lexical variables are a compile-time concept, not a read-time concept.
You might want to take a look at:
http://www.flownet.com/ron/packages.pdf
http://www.flownet.com/ron/specials.pdf
rg
Oh dear, you really are confused.
Lexical variables certainly are bound. They are not "declared"
(whatever that means -- you can declare the *type* of a lexical
variable's value, but that seems unlikely to be what you meant).
And dynamic variables are not symbols, they are bindings (so are lexical
variables). Please read:
http://www.flownet.com/ron/specials.pdf
rg
>
> I think you are confused. There is no such thing as "the *package*
> table", and the idea of "reading a lexical variable" is non-sensical.
> Lexical variables are a compile-time concept, not a read-time concept.
Not as much as you seem to think. I had to look at Rob Warnoks code to
realize (let (x) (symbolp 'x)) -> T
Clearly the reader on encoundering 'x creates a symbol.
Most symbols created by defvar, defparameter et al. are stored in the
packages symbol-table. The current package is *package* so this it where
it puts these symbols. That is not the case with lexical variables.
Reading up on AllegroCL's environment interface it I see that there is a
seperate lexical-environment where these symbols go.
These are created at compile time and can disappear by the time the
program is run.
A lexical variable can be checked for by (eq :special (sys:variable-
information 'whatever))
In SBCL there is a cltl2:variable-information that works the same way.
--
John Thingstad
I didn't mean to stop or interrupt you, just point out that there's no
equivalent of boundp for lexical variables. I may be wrong, but the
fact that the OP explicitly mentioned he preferred something
"equivalent to boundp" makes me suspect he hasn't very clear ideas
about lexical and special bindings.
Peace,
Alessio
Then how do you explain (let (x) (find-symbol "X")) -> X?
In code read at runtime, the above always returns X. If you compile
that code, open a new Lisp session, and load the compiled code, it
might return NIL, since the symbol might not be present anymore.
Bye,
Ale
Actually, the reader created the symbol X earlier, when it saw "(x)"... ;-}
+---------------
| Most symbols created by defvar, defparameter et al. are stored in the
| packages symbol-table. The current package is *package* so this it where
| it puts these symbols. That is not the case with lexical variables.
+---------------
(*sigh*) Symbols are *NOT* "created by DEFVAR, DEFPARAMETER, etc."!!
Symbols are created *ONLY* by the reader!! [Well, or explicitly INTERN'd
or MAKE-SYMBOL'd or GENSYM'd by the programmer.] Thus lexical variables
*do* involve symbols created by the reader as well.
What DEFVAR, etc., do is change some *attributes* of a symbol related
to that symbol's interpretation as a global (or special) variable,
such as set what SYMBOL-VALUE will return when called with that
symbol as an argument.
[ASIDE: Note that this says *nothing* about symbols having "slots"!!
The notion of symbols having slots is a holdover from earlier Lisps.
"We don' need no stinkin' slots!" All that is necessary is that
SYMBOL-{VALUE,FUNCTION,PLIST} behave "as if" there are slots of
those names. E.g., while symbols in CMUCL do happen to still have a
value slot in the internal representation, they *don't* have a function
slot!!! Really! The function value is stored somewhere else entirely
(the INFO database, actually).]
Now, symbols are *also* used as a way to *name* lexical variables,
but *only* their identity is used -- no other attributes. That's why
one can perform "alpha conversion" (q.v.) -- capture-free renaming
of lexical variables -- *without* changing the semantics of the code
at all. The names have no more (and no less!) significance than the
numbers in the #n= and #n# readmacros. Their job is simply to be a
unique [within a lexical scope] identity that can be used as a shorthand
to refer to a place [the actual "variable"] holding a value. And that
identity becomes meaningless once the code has been compiled or even
just "pre-processed" by an interpreter. [E.g., the first time a function
is executed in the SCM Scheme interopreter, it replaces all symbols used
as lexical variables by #<lex:F:L> immediates, where F is the number of
frames up to look and L is an offset-within-frame.]
+---------------
| Reading up on AllegroCL's environment interface it I see that
| there is a seperate lexical-environment where these symbols go.
| These are created at compile time and can disappear by the time the
| program is run.
+---------------
The *names* disappear, but the *bindings* [the place/value pairs] don't.
[The places may also get moved from their initial assignments during
compilation, e.g., from the heap (general case) to the stack (if certain
conditions are met) to a machine register (even more conditions).]
> The Thu, 19 Nov 2009 21:44:55 -0800, Ron Garret wrote:
>
> >
> > I think you are confused. There is no such thing as "the *package*
> > table", and the idea of "reading a lexical variable" is non-sensical.
> > Lexical variables are a compile-time concept, not a read-time concept.
>
> Not as much as you seem to think. I had to look at Rob Warnoks code to
> realize (let (x) (symbolp 'x)) -> T
That's true, but not for the reason you think. (symbolp 'x) always
returns T regardless of what it's wrapped in.
> Clearly the reader on encoundering 'x creates a symbol.
That's right.
> Most symbols created by defvar, defparameter et al.
No. DEFVAR et al. do not create symbols. Please read the references I
pointed you to.
> are stored in the
> packages symbol-table. The current package is *package* so this it where
> it puts these symbols. That is not the case with lexical variables.
No. You are badly confused. Symbols are not variables, they are the
*names* of variables. Variables are *bindings*.
> Reading up on AllegroCL's environment interface it I see that there is a
> seperate lexical-environment where these symbols go.
That's right.
> These are created at compile time and can disappear by the time the
> program is run.
That's not quite right. The *names* of lexical variables can be
compiled away as an (optional) optimization. But the lexical variables
themselves still exist at run time. If they didn't, it would not be
possible to create lexical closures.
All your misconceptions are very common, which is the reason that I
wrote the references I pointed you to earlier. Please read them.
rg
> On Nov 20, 9:13 am, John Thingstad <jpth...@online.no> wrote:
>> The Thu, 19 Nov 2009 21:44:55 -0800, Ron Garret wrote:
>>
>>
>>
>> > I think you are confused. There is no such thing as "the *package*
>> > table", and the idea of "reading a lexical variable" is non-sensical.
>> > Lexical variables are a compile-time concept, not a read-time
>> > concept.
>>
>> Not as much as you seem to think. I had to look at Rob Warnoks code to
>> realize (let (x) (symbolp 'x)) -> T
>> Clearly the reader on encoundering 'x creates a symbol.
>
> Then how do you explain (let (x) (find-symbol "X")) -> X?
>
It is true that the symbol is created when (let (x) ...) is run.
However (symbolp 'x) would always return X wether it already existed or
not. So you example is what I ment.
--
John Thingstad
>
> All your misconceptions are very common, which is the reason that I
> wrote the references I pointed you to earlier. Please read them.
>
> rg
Looking at your comments I think the way it is written needs improving. I
do think I basically understand it though.
If read up a couple of post's for instance you would see that I am aware
that it is the reader that creates symbols and that defvar creates a
binding to that symbol. The symbol in turn get's assigned a binding to
the object contaning the value.
This sort of thing would be SO much simpler to explain/grasp if you could
draw a diagram..
(Warnock explains that this too is a simplification, but at least it will
always look like it does from the CL interface.)
PS: I did reread your 'Idiot's guide to symbols'. In fact I went looking
for it before I wrote the original post but couldn't find it.
--
John Thingstad
> The Fri, 20 Nov 2009 00:39:38 -0800, Alessio Stalla wrote:
>
> > On Nov 20, 9:13 am, John Thingstad <jpth...@online.no> wrote:
> >> The Thu, 19 Nov 2009 21:44:55 -0800, Ron Garret wrote:
> >>
> >>
> >>
> >> > I think you are confused. There is no such thing as "the *package*
> >> > table", and the idea of "reading a lexical variable" is non-sensical.
> >> > Lexical variables are a compile-time concept, not a read-time
> >> > concept.
> >>
> >> Not as much as you seem to think. I had to look at Rob Warnoks code to
> >> realize (let (x) (symbolp 'x)) -> T
> >> Clearly the reader on encoundering 'x creates a symbol.
> >
> > Then how do you explain (let (x) (find-symbol "X")) -> X?
> >
>
> It is true that the symbol is created when (let (x) ...) is run.
No, that is not true. The symbol is created when "x" is *read*.
> However (symbolp 'x) would always return X wether it already existed or
> not.
That's kind of like saying "1+1=2 whether or not 1 exists or not."
It's true that (symbolp 'x) will always return T, but it is not true (or
at least badly misleading) that this is "whether X already existed or
not". It is simply not possible for the form (symbolp 'x) to exist
without the symbol X existing.
rg
JT> Because lexical variables are never bound at all.
Dude, learn terminology first:
----
http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo_b.htm#binding
binding n. an association between a name and that which the name denotes.
``A lexical binding is a lexical association between a name and its value.''
When the term binding is qualified by the name of a namespace, such as
``variable'' or ``function,'' it restricts the binding to the indicated
namespace, as in: ``let establishes variable bindings.'' or ``let
establishes bindings of variables.''
http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo_l.htm
lexical binding n. a binding in a lexical environment.
lexical environment n. that part of the environment that contains bindings
whose names have lexical scope. A lexical environment contains, among other
things: ordinary bindings of variable names to values, lexically established
bindings of function names to functions, macros, symbol macros, blocks,
tags, and local declarations (see declare).
----
OP phrased it correctly: "Is there a way to find out if a symbol has a
binding in the lexical environment ?"
JT> They are declared or
JT> they are undeclared. You can check if a lexical variable is DECLARED at
JT> compile time.
While I understand what you mean, that is not terminology which is used in
Common Lisp.
One more relevant definition:
bound adj., v.t. 1. adj. having an associated denotation in a binding. ``The
variables named by a let are bound within its body.'' See unbound. 2. adj.
having a local binding which shadows[2] another. ``The variable
*print-escape* is bound while in the princ function.'' 3. v.t. the past
tense of bind.
Alessio seems to totally misunderstand how the REPL works, so I'll
try to give a beginner-level explanation.
I assume you mean that you have started up an interactive Lisp
session, and you're looking at the Read-Eval-Print loop, and then
you type in the following line of text (without leading spaces):
(let (x) (find-symbol "X"))
and the REPL promptly types back out at you this line (again wls):
X
Is that what you're telling us? If so, here's what is happening:
First READ is called to input one or more lines of input until
parens match (and strings are closed etc., all properly nested) and
simultaneously try to parse it (which is how it knows everything
matches, i.e. it sees that it's back at the toplevel of the parser
which then returns the parse-tree).
In your case, the parser sees the open parens, which goes into a
lower level of parse, sees the word "let" which sees there already
is a symbol (in the current package, i.e. lisp-user or something
like that) by that name so it just returns a pointer to that symbol
(at the lower level of parse) which the top level of parse builds
into the CAR of a CONS cell. Next it sees the second open parens,
and goes into a third level of parse. The third level sees the word
"x", but there's no symbol by that name (in the current package) so
it creates a new symbol by that name and returns that symbol which
is the built into the CAR of a CONS cell. Then it sees the
close-parens, so it puts NIL into the CDR of that same CONS cell to
end the list, and returns that entire one-element list to the
second level of parse. Next another open parens is seen, dropping
to third level, the word "find-symbol" is seen, but that symbol
already exists, so the pointer is put into the second-level list,
then the string "X" is seen, which is returned as-is and added to
the second-level list, then the close-parens is seen which finishes
the second level list so that's returned to the top parse and added
to that list, which now has three elements, then the final
close-paren is seen which closes that top list and returns it from
the toplevel READ of the REPL.
Summarizing all that, two already-existing symbols have been
recognized, one new symbol has been created, one string has been
built, and a two-level list has been created and returned.
Next, that 2-level list is passed to EVAL, which might interpret
directly, or might compile first then run the result, depending on
implementation and/or compiler settings. But however it works, it
sets up a lexical frame that to the *compiler* or *interpretor* is
known as containing a variable called x, but has nothing to do with
the global variable x (the value of the symbol X) which is
currently not bound, i.e. the symbol exists but doesn't have any
value. The initial value of that lexical variable in that lexical
frame is set to NIL because you just said the name of the variable
in the LET binding clause instead of the variable and value. Next,
while *in* that lexical frame, the string "X" is passed to the
function find-symbol, which looks in the current package to see if
there's a symbol there, and indeed it finds the X symbol that was
created by READ a moment earlier, and returns *that* symbol. This
has nothing to do with the lexical frame with the X lexical
variable, even though the syntax that was read in to specify this
form happened to have the word X which created that symbol in the
current package. That return value from find-symbol, namely the
symbol X, is now passed up to the implicit PROGN of the LET form,
and since it's the last form, the value is passed up as return
value of the implicit PROGN. The lexical form is now removed, and
that return value from implicit PROGN is now passed back as return
value of the LET form, which is then the return value from EVAL.
In summary, the lexical binding x was never used in any way, only
the package was checked to see if a symbol called "X" was leftover
from the earlier READ, and that symbol is returned.
Finally, the return value from EVAL is passed to PRINT, so it
prints X.
Try this instead (in a fresh Lisp):
(let (x)
(let ((y (find-symbol "X")))
(list x y (boundp y))))
=> (NIL X NIL)
That shows the lexical X has value NIL (first element of the returned list),
but the **SYMBOL** found by "X" (second element of returned list)
isn't bound (as shown by third element of returned list).
Now try this (in a fresh Lisp):
(let ((x "Lex"))
(let ((y (find-symbol "X")))
(list x y (boundp y) (set y "Glob") (boundp y) (symbol-value y))))
=> ("Lex" X NIL "Glob" T "Glob")
Now the lexical binding is the string "Lex" instead of NIL, and the
global symbol initially is not bound but gets bound to the string
"Glob" midway through building the LIST.
Note that (setq x "Glob") in this context would change the value of
the *lexical* binding, not the binding of the symbol X.
> In code read at runtime, the above always returns X.
No it doesn't. Try this (in a fresh Lisp):
(defconstant $form$ '(let (x) (find-symbol "X")))
(eval $form$) ;There still is a symbol by the name "X" i the current plackage,
; so this returns X. CMUCL also warns that lexical X never used.
(symbol-package (caadr $form$)) ;=> #<The COMMON-LISP-USER package, ...>
(unintern (caadr $form$))
(symbol-package (caadr $form$)) ;=> NIL
(eval $form$) ;There is no longer a symbol by that name in the current package,
; so this returns NIL.
Thus, evaluating exactly the same $form$ two different times,
yields different results, depending on whether the current package
still has the symbol X left-over from READ of the DEFCONSTANT line.
(read-from-string "X") ;Creates yet another symbol named X in current package.
(eval $form$) ;Since the current package *now* has a symbol called "X",
; a *different* symbol from what it had before the
; unintern, it prints X again.
Now if we had saved the X we got from the first (eval $form$) and
the X we got from the third (eval $form$) and compared them, we'd
find they are *not* EQ hence *not* the same symbol, even though
both are called X.
Now try this (in a fresh Lisp):
(list
(defconstant $form$ '(let (x) (find-symbol "X")))
(let ((val (eval $form$))) (format t "First eval gives: ~S~%" val) val)
(symbol-package (caadr $form$))
(unintern (caadr $form$))
(symbol-package (caadr $form$))
(let ((val (eval $form$))) (format t "Second eval gives: ~S~%" val) val)
(read-from-string "X")
(let ((val (eval $form$))) (format t "Third eval gives: ~S~%" val) val)
)
First eval gives: X
Second eval gives: NIL
Third eval gives: X
=> ($FORM$ #:X #<The COMMON-LISP-USER package, 3/9 internal, 0/9 external>
T NIL NIL X X)
Notice how exactly the same symbol, the second element of the
returned list, printed as X while the list was being built, before
the symbol was uninterned, but now at the very end when the LIST
return value is printed that second element now prints as #:X
because it's no longer in the current package and in fact not in
*any* package.
Anyway, the point is that I read in that form just once, bound it
as a constant to the symbol $FORM$, and evaluated it three
different times, getting three different results, two of which
*looked* the same when immediately printed but in fact were
*different* symbols both called "X". So you were wrong when you
said that form always returns X. One of the three times it returned
NIL instead of any X, and the other two times it returned two
different symbols each called "X". If I wanted, I could make
evaluation of that very same form return a hundred different
values, each a different symbol called "X" (in a fresh Lisp):
(defconstant $form$ '(let (x) (find-symbol "X")))
(loop for n from 101 to 110
collect (let* ((sym (read-from-string "X"))
(dummy1 (format t "~S " sym))
(str (format nil "P~D" n))
(pak (make-package str))
(dummy2 (unintern sym))
(dummy3 (format t "~S " sym))
(dummy4 (import sym pak))
(dummy5 (format t "~S / " sym)))
sym))
No, the question was rhetorical, I meant it as a counterexample for
John Thingstad, who said
"[since] (let (x) (symbolp 'x)) -> T [then c]learly the reader on
encoundering 'x creates a symbol. Most symbols [are] created by
defvar..."
I wanted to show him that the symbol X is not created when
"encountering" 'x but earlier, the first time x is read. Anyway your
explanation is much clearer :)
Ok, I should have said "read and immediately executed" ;) Yours is a
very nice example of the fact that Lisp code is actually made of Lisp
data, not text.
Ideally I was looking for a portable solution but this is useful to
know. Since during the course of the thread it was asked what I want to
achieve, here it is:
In one of my posts in the thread "Remembering information during
compilation"
< http://groups.google.co.uk/group/comp.lang.lisp/browse_thread/thread/460e44871936c99c >
I presented the following piece of code:
(let ((a (gensym "memory-var-")))
(defmacro memory (&body body)
`(progn
(if (boundp ',a)
(incf ,a)
(defvar ,a 1))
(symbol-macrolet ((cell ,a))
(prog1
,@body
(decf ,a))))))
So I wanted to write the analogous thing but making 'a a lexical instead
of a special variable. Your macro makes this possible:
; SBCL specific code
(require "sb-cltl2")
(defmacro lexically-bound-p (variable &environment env)
(eq :lexical (sb-cltl2:variable-information variable env)))
(let ((a (gensym "memory-var-")))
(defmacro memory (&body body)
`(if (lexically-bound-p ,a)
(let ((,a (1+ ,a)))
(symbol-macrolet ((cell ,a))
,@body))
(let ((,a 1))
(symbol-macrolet ((cell ,a))
,@body)))))
It's interesting to note that the 2 definitions of memory do not behave
identically. This can be seen in the following piece of code which also
appeared in the other thread:
(let ((f1
(memory
(lambda ()
(memory (format t "Calling f1 gives ~a~%" cell))))))
(funcall f1)
'| |)
Perhaps I should have said "analog" or "similar" instead of
"equivalent". But I did say "Ideally" which indicated that I was also
interested in approximations to whatever would pass as "equivalent".
> Special variables and lexical variables are different, hence constructs
> which check their presence must be different and they must reflect
> that difference.
>
> Special variables have indefinite scope and dynamic extent.
> This means that boundp-for-special-variable should do a check in runtime
> and it should accept any symbol.
>
> Lexical variables have lexical scope and indefinite extent.
> Therefore, boundp-for-lexical-variable should work statically, at compile
> time, because that information is available at compilte time, and perhaps
> *only* at compile time.
My intention was to use it at compile time as can be seen from the code
I posted elsethread. I never gave any thought to whether the predicate
I was looking for would also work at runtime.
> So if we assume that OP knows what lexical variables are, answer
> which Lars gave was a correct answer.
>
> Of course, there is a chance that OP does not really understand how
> lexical variables work, but why should we assume ignorance of a poster
> if he gave us no reasons to?
I believe I understand the difference between lexical and special
variables but it's possible that I don't appreciate all the
implications of the difference.
--
Never attribute to conspiracy what can adequately be explained by
shared attitudes.