From: Timofei Shatrov
Subject: A little problem
Date: 
Message-ID: <430047ea.8931699@news.readfreenews.net>
This is probably a stupid question, but I cannot figure out how to get a
value of a variable :) Suppose the value of y is x and the value of x is
42. What do I need to do with y to get 42?

symbol-value doesn't work when the value of x is lexically scoped.

(setf x 1) => 1
(setf y 'x) => X
(let ((x 42)) (symbol-value y)) => 1


-- 
|a\o/r|,-------------.,---------- Timofei Shatrov aka Grue ------------.
| m"a ||FC AMKAR PERM|| mail: grue at mail.ru  http://grue3.tripod.com |
|  k  ||  PWNZ J00   || Kingdom of Loathing: Grue3 lvl 18 Seal Clubber |
`-----'`-------------'`-------------------------------------------[4*72]

From: alexander
Subject: Re: A little problem
Date: 
Message-ID: <1124098801.533509.278840@f14g2000cwb.googlegroups.com>
Timofei Shatrov wrote:

> (setf x 1) => 1
> (setf y 'x) => X
> (let ((x 42)) (symbol-value y)) => 1


It's funny but cmucl prints 42. May be bag ?
From: alexander
Subject: Re: A little problem
Date: 
Message-ID: <1124099676.849711.79030@o13g2000cwo.googlegroups.com>
Cmucl prints 42 then I evaluate them from toplevel and 1 then I compile
whole file.Why?
From: Pascal Bourguignon
Subject: Re: A little problem
Date: 
Message-ID: <87r7cvfkfq.fsf@thalassa.informatimago.com>
"alexander" <········@gmail.com> writes:
> Cmucl prints 42 then I evaluate them from toplevel and 1 then I compile
> whole file.Why?

Because this divergence between the interpreter and the compiler is
allowed by the CL specifications.

-- 
"Specifications are for the weak and timid!"
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86slxbbk0m.fsf@drjekyll.mkbuelow.net>
"alexander" <········@gmail.com> writes:

>Timofei Shatrov wrote:
>
>> (setf x 1) => 1
>> (setf y 'x) => X
>> (let ((x 42)) (symbol-value y)) => 1
>
>It's funny but cmucl prints 42. May be bag ?

Cmucl[1] displays 42 when typing it into the repl, or loading it
directly from a .lisp file, and 1 when loading it from a compiled
FASL. I'd say it's a bug; it should at least decide on which value to
evaluate to, irrespective of whether it's compiled or interpreted.
Also, from my (limited) understanding, a result of 42 is wrong,
since the x is not a free variable in some procedure but y directly
references the symbol x which is interned as the toplevel special
variable.

mkb.

[1] version:
CMU Common Lisp 19a, running on luzifer.incubus.de
With core: /usr/local/lib/cmucl/lib/lisp.core
Dumped on: Tue, 2004-08-03 18:19:33+02:00 on snapdragon.csl.sri.com
See <http://www.cons.org/cmucl/> for support information.
Loaded subsystems:
    Python 1.1, target Intel x86
    CLOS based on Gerd's PCL 2004/04/14 03:32:47
From: Christophe Rhodes
Subject: Re: A little problem
Date: 
Message-ID: <sq7jenldwd.fsf@cam.ac.uk>
Matthias Buelow <···@incubus.de> writes:

> "alexander" <········@gmail.com> writes:
>
>>Timofei Shatrov wrote:
>>
>>> (setf x 1) => 1
>>> (setf y 'x) => X
>>> (let ((x 42)) (symbol-value y)) => 1
>>
>>It's funny but cmucl prints 42. May be bag ?
>
> Cmucl[1] displays 42 when typing it into the repl, or loading it
> directly from a .lisp file, and 1 when loading it from a compiled
> FASL. I'd say it's a bug; it should at least decide on which value to
> evaluate to, irrespective of whether it's compiled or interpreted.
> Also, from my (limited) understanding, a result of 42 is wrong,
> since the x is not a free variable in some procedure but y directly
> references the symbol x which is interned as the toplevel special
> variable.

All you people giving your opinions on whether it's a bug or not have
read the CMUCL FAQ, right?  (It would be ridiculous to expect you to
read the standards document as well, obviously).

Christophe
From: Edi Weitz
Subject: Re: A little problem
Date: 
Message-ID: <u64u77b0u.fsf@agharta.de>
On 15 Aug 2005 02:40:01 -0700, "alexander" <········@gmail.com> wrote:

> Timofei Shatrov wrote:
>
>> (setf x 1) => 1
>> (setf y 'x) => X
>> (let ((x 42)) (symbol-value y)) => 1
>
> It's funny but cmucl prints 42. May be bag ?

No.  Are you sure you haven't seen a couple of warnings when
evaluating your code?  That should give you a hint.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Stefan Scholl
Subject: Re: A little problem
Date: 
Message-ID: <ddpl4l$pd1$02$1@news.t-online.com>
Funny how nowadys the first questions from newbies to _every_ language
regard variable variables.

Too much PHP?
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <867jend19i.fsf@drjekyll.mkbuelow.net>
····@mail.ru (Timofei Shatrov) writes:

>This is probably a stupid question, but I cannot figure out how to get a
>value of a variable :) Suppose the value of y is x and the value of x is
>42. What do I need to do with y to get 42?
>
>symbol-value doesn't work when the value of x is lexically scoped.
>
>(setf x 1) => 1
>(setf y 'x) => X
>(let ((x 42)) (symbol-value y)) => 1

Hint: the x you're binding to 42 isn't the same symbol x you've bound
to 1.

mkb.
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcowtmno97h.fsf@shuttle.math.ntnu.no>
+ Matthias Buelow <···@incubus.de>:

| ····@mail.ru (Timofei Shatrov) writes:
| 
| >(setf x 1) => 1
| >(setf y 'x) => X
| >(let ((x 42)) (symbol-value y)) => 1
| 
| Hint: the x you're binding to 42 isn't the same symbol x you've bound
| to 1.

Yes, it is.  But it's not the same variable.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86zmrjbl4o.fsf@drjekyll.mkbuelow.net>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

>Yes, it is.  But it's not the same variable.

*sigh* get the facts right before trying to smartass others.

mkb.
From: Edi Weitz
Subject: Re: A little problem
Date: 
Message-ID: <uacjj7b81.fsf@agharta.de>
On Mon, 15 Aug 2005 11:32:55 +0200, Matthias Buelow <···@incubus.de> wrote:

> *sigh* get the facts right before trying to smartass others.

Isn't it kind of funny that only a couple of hours ago you explained
to us that Common Lisp is a "dead, bloated whale" and now you're
demonstrating that you actually have no clue what you're talking
about?

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86hddrbig1.fsf@drjekyll.mkbuelow.net>
Edi Weitz <········@agharta.de> writes:

>Isn't it kind of funny that only a couple of hours ago you explained
>to us that Common Lisp is a "dead, bloated whale" and now you're
>demonstrating that you actually have no clue what you're talking
>about?

So you claim that the very same symbol X is bound to 42 somewhere
during execution of that code?

mkb.
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcobr3zlayp.fsf@shuttle.math.ntnu.no>
+ Matthias Buelow <···@incubus.de>:

| Edi Weitz <········@agharta.de> writes:
| 
| >Isn't it kind of funny that only a couple of hours ago you explained
| >to us that Common Lisp is a "dead, bloated whale" and now you're
| >demonstrating that you actually have no clue what you're talking
| >about?
| 
| So you claim that the very same symbol X is bound to 42 somewhere
| during execution of that code?

I believe it is, if you're running interpreted.  It will then be bound
to 42 (or perhaps more precisely, to a location containing 42) in the
lexical environment, which shadows the global binding.  My point is
that the very same symbol X is used in both places: That is fixed by
the reader.  In compiled code, as you quite correctly states
elsewhere, the compiler will have replaced the variable name with a
memory reference, so the lexical binding exists only in a conceptual
sense, rather than in actual reality.  (If you were to end up in the
debugger, things may get a bit thornier, but let us not go there.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <868xz3bg7l.fsf@drjekyll.mkbuelow.net>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

>I believe it is, if you're running interpreted.  It will then be bound
>to 42 (or perhaps more precisely, to a location containing 42) in the
>lexical environment, which shadows the global binding.  My point is

Perhaps you're thinking about something like fluid-let, as is
available with some Schemes, for emulating special (dynamic)
variables? That's not the same for Lisp. Here a "real" new symbol is
bound in the environment, with the same symbol name as the one in the
toplevel environment. The difference between dynamic lookup and
lexical reference then would only be that in the dynamic case, the
environments are searched for the named symbol bottom-up, whereas in
the lexical case, a reference would be established at the time of
definition (this probably requires at least some minimal source
transformation, so it might not be possible to implement lexical
environments in a pure interpreter that just walks the unmodified
source and creates symbol bindings because you would have to change
the actual references, or it would degenerate into more or less the
dynamic case, but I might be wrong about that.)

mkb.
From: ··@codeartist.org
Subject: Re: A little problem
Date: 
Message-ID: <1124119937.498623.142290@f14g2000cwb.googlegroups.com>
Matthias Buelow schrieb:
> Perhaps you're thinking about something like fluid-let, as is
> available with some Schemes, for emulating special (dynamic)
> variables? That's not the same for Lisp. Here a "real" new symbol is
> bound in the environment, with the same symbol name as the one in the
> toplevel environment.

This is nonsense. There is no new symbol involved. There are two
classical implementations of dynamic variable lookup in Lisp: Deep
Binding and shallow binding.

Deep Binding:
Particularly easy to implement in interpreters. It uses an alist to
store the name->value mapping of the variables. When a local binding is
established one just pushes another name-value pair on the alist which
shadows any older pairs. The downside is that variable lookup is no
longer constant time because you have to search for the variable in the
alist (which grows longer when the calls get deeper). If you would use
a new symbol then  lookup would not find the correct name-value pair in
the alist.

Shallow Binding:
In shallow binding you always use the memory cell allocated for the
symbol-value slot in the symbol to access the value. Variable access is
therefore constant time. If a local variable binding is established
which shadows another variable, the current value of symbol-value is
saved on the stack and the new value is written into the symbol-value
slot. If the dynamic scope of the local variable is left, symbol-value
gets reset to the value saved on the stack. The performance gain in
variable access it paid by additional overhead in the function call
procedure. If you would use a new symbol the symbol-value slot would be
another one and you would lookup the wrong thing.  

Jochen Schmidt
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pco3bpbl764.fsf@shuttle.math.ntnu.no>
+ Matthias Buelow <···@incubus.de>:

| Perhaps you're thinking about something like fluid-let, as is
| available with some Schemes, for emulating special (dynamic)
| variables?

It's been too long since I knew anything about Scheme, so I can't tell
if what I was thinking of is something like fluid-let.

| That's not the same for Lisp. Here a "real" new symbol is bound in
| the environment, with the same symbol name as the one in the
| toplevel environment.

That is not how I understand it.  HyperSpec:

  let and let* create new variable bindings and execute a series of
  forms that use these bindings. let performs the bindings in parallel
  and let* does them sequentially.

Nowhere do I see a mention of new symbols, just new bindings for the
same symbol.  Though I suppose thinking of it your way may not hurt,
if you can't tell the difference by experimenting with a conforming
Lisp.  I don't know.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86y8739xlu.fsf@drjekyll.mkbuelow.net>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

>+ Matthias Buelow <···@incubus.de>:
>
>| Perhaps you're thinking about something like fluid-let, as is
>| available with some Schemes, for emulating special (dynamic)
>| variables?
>
>It's been too long since I knew anything about Scheme, so I can't tell
>if what I was thinking of is something like fluid-let.
>
>| That's not the same for Lisp. Here a "real" new symbol is bound in
>| the environment, with the same symbol name as the one in the
>| toplevel environment.
>
>That is not how I understand it.  HyperSpec:
>
>  let and let* create new variable bindings and execute a series of
>  forms that use these bindings. let performs the bindings in parallel
>  and let* does them sequentially.
>
>Nowhere do I see a mention of new symbols, just new bindings for the
>same symbol.  Though I suppose thinking of it your way may not hurt,
>if you can't tell the difference by experimenting with a conforming
>Lisp.  I don't know.

Hmm, well, from my understanding, "new variable binding" normally
means a new entry in the environment for a symbol of the same name. It
doesn't temporarily set the old symbol to a new value (which fluid-let
would do, in order to emulate special variables, which Scheme doesn't
have).

Informally, as I understand it, it often works like the following: you
have environment frames (at least conceptually) that you could, for
sake of visualization, imagine to be a stack:

1:[ A -> 1 ]
2:[ B -> 2 ]
3:[ C -> 3 ]

and then you establish a new binding for, say, B in a let:

  (let ((x 1) (y 2) (b 1235))
    ...)

which adds the following bindings:

n:  [ X -> 1 ]
n+1:[ Y -> 2 ]
n+2:[ B -> 1235 ]

Now, if B is special, a reference to B would then walk those
environment "stack frames" downwards from the current top of the
stack, until it finds a binding named "B". This value is then used.

If B is lexical, a reference contains the address (the number in front
of the respective frame) and not the name, and looks it up directly.
This number equals the address of the symbol at the time the reference
was defined, and not at the time when it is used.

So if, say, C is bound to B before the let, and B is lexical (as
in the example which we discuss), then C would contain the address 2
and the earlier binding of the symbol B would be used.

Whereas if C is bound to B before the let but B is special, then C
would "contain"[1] the symbol "name" B and would look up the current
binding for B on the environment stack, as explained above.

mkb.

[1] This could be the same reference as before, but with the variable
flagged as special in the symbol so that the interpreter knows that it
shouldn't take the value from that binding but to look it up instead.
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcoy873jomu.fsf@shuttle.math.ntnu.no>
+ Matthias Buelow <···@incubus.de>:

| Harald Hanche-Olsen <······@math.ntnu.no> writes:
| 
| >Nowhere do I see a mention of new symbols, just new bindings for the
| >same symbol.  Though I suppose thinking of it your way may not hurt,
| >if you can't tell the difference by experimenting with a conforming
| >Lisp.  I don't know.
| 
| Hmm, well, from my understanding, "new variable binding" normally
| means a new entry in the environment for a symbol of the same name.

Indeed, a new entry in the environment for the same symbol.  As you
explained it, there is no need for different symbols of the same
name.  Just let the same symbol be present several places in your
(conceptual) stack, and your explanation works just fine.  I think our
disagreement is evaporating.

| It doesn't temporarily set the old symbol to a new value (which
| fluid-let would do, in order to emulate special variables, which
| Scheme doesn't have).

Ah.  So that is what fluid-let does.  I agree that CL doesn't.

| So if, say, C is bound to B before the let, and B is lexical (as
| in the example which we discuss), then C would contain the address 2
| and the earlier binding of the symbol B would be used.

Now I'm getting confused again.  What do you mean by C being bound to
B?  If you mean (let ((c b)) ...) then what is happening is that B is
evaluated, as a lexical or special variable as the case may be, and
the resulting value is stored in C.  Certainly, C would no longer
refer to B.  In other words,

(let ((b 2))
  (let ((c b))
    (setf b 42)
    c))
=> 2 (and not 42)

Or, if you mean (let ((c 'b)) ...) then the value of C in no way
reflects the status of B or any information of its value in the
environment.

(eq 'b
    (let ((b 2))
      (let ((c 'b))
	c)))
=> T

I almost imagine your statements implying that the above should return
NIL, but I hope you don't really mean that.  I'll assume that I either
misunderstood, or that you misspoke in the heat of the moment.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86u0hr9sx9.fsf@drjekyll.mkbuelow.net>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

>| So if, say, C is bound to B before the let, and B is lexical (as
>| in the example which we discuss), then C would contain the address 2
>| and the earlier binding of the symbol B would be used.
>
>Now I'm getting confused again.  What do you mean by C being bound to
>B?  If you mean (let ((c b)) ...) then what is happening is that B is

No, I mean (setq c 'b), analogous to the example by the OP that we are
discussing.

>Or, if you mean (let ((c 'b)) ...) then the value of C in no way
>reflects the status of B or any information of its value in the
>environment.
>
>(eq 'b
>    (let ((b 2))
>      (let ((c 'b))
>	c)))
>=> T
>
>I almost imagine your statements implying that the above should return
>NIL, but I hope you don't really mean that.  I'll assume that I either
>misunderstood, or that you misspoke in the heat of the moment.

No, not that they are different wrt. eq, only that there is a complete
new "instance" of the symbol on the "stack" which will get used,
according to scoping rules, so that it is basically like a new symbol
with the same name, but apparently this isn't so, as one can see by
probing the property list:

(let ((a nil))
  (let ((a nil))
    (setf (get 'a 'foo) 'bar))
  (get 'a 'foo))
--> BAR

Weird, I think that's just inconsequential... somehow the deeper one
pokes, the weirder it gets (imho). Why are some cells copied but
others (like the plist) are shared with the original symbol?

mkb.
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcou0hrjke2.fsf@shuttle.math.ntnu.no>
+ Matthias Buelow <···@incubus.de>:

| Harald Hanche-Olsen <······@math.ntnu.no> writes:
| 
| >| So if, say, C is bound to B [...]
| >
| >Now I'm getting confused again.  What do you mean by C being bound to
| >B?  If you mean [...]
| 
| No, I mean (setq c 'b),

Oh.  I don't call that binding (by which I mean establishing a new
binding), I call it changing an existing binding.  Or more briefly,
setting a variable.  LET, LET* and calling a function results in new
bindings being established.  SETQ does not.

| analogous to the example by the OP that we are discussing.

Yeah, I forgot the context, which contributed to my confusion.

| (let ((a nil))
|   (let ((a nil))
|     (setf (get 'a 'foo) 'bar))
|   (get 'a 'foo))
| --> BAR
| 
| Weird, I think that's just inconsequential... somehow the deeper one
| pokes, the weirder it gets (imho). Why are some cells copied but
| others (like the plist) are shared with the original symbol?

Perhaps because "value cell" is a red herring, particularly when used
with lexical variables.  The plist is a property of the symbol alone.
The symbol's binding in the current environment is a combined property
of the symbol and said environment.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: lin8080
Subject: Re: A little problem
Date: 
Message-ID: <4304657D.42A42EDD@freenet.de>
Edi Weitz schrieb:
> On Mon, 15 Aug 2005 11:32:55 +0200, Matthias Buelow <···@incubus.de> wrote:

> > *sigh* get the facts right before trying to smartass others.

> Isn't it kind of funny that only a couple of hours ago you explained
> to us that Common Lisp is a "dead, bloated whale" and now you're
> demonstrating that you actually have no clue what you're talking
> about?

It shows the frustration newbies can step in when using lisp ... 
so, better do some tutorials then hack on newbies, right?

stefan

*deckung_such*
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcoslxbo8y9.fsf@shuttle.math.ntnu.no>
+ ····@mail.ru (Timofei Shatrov):

| This is probably a stupid question,

Yes it is, but (hopefully) not because you're stupid, rather because
you don't know Lisp very well yet.

| but I cannot figure out how to get a
| value of a variable :) Suppose the value of y is x and the value of x is
| 42. What do I need to do with y to get 42?

Your question indicates to me that you're used to languages that are
heavily geared towards interpreted use.  Lisp just doesn't work this
way at all.

If you're trying to solve a real problem, tell us what it is, and we
might come up with a more appropriate approach.  If you're just
playing around with the language, trying to figure out how to do
things the same way you do them in some other language, I suggest it
is the wrong way to learn a new language.  A different programming
language is more than just surface syntax on top of the same concepts;
the underlying concepts themselves are different.  You need to
understand that in order to make progress.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Andreas Thiele
Subject: Re: A little problem
Date: 
Message-ID: <ddppu4$sah$00$1@news.t-online.com>
"Timofei Shatrov" <····@mail.ru> schrieb im Newsbeitrag
·····················@news.readfreenews.net...
>
> This is probably a stupid question, but I cannot figure out how to get a
> value of a variable :)
> ...

There is a great paper on variable scope by Ron Garret at

http://www.flownet.com/gat/

or directly

http://www.flownet.com/gat/specials.pdf

CLHS explicitely says "symbol-value cannot access the value of a lexical
variable.".

Indeed I somehow wonder about this. Obviously symbol-value doesn't consider
the environment. I still wonder why this is so and what symbol-value is for?

Andreas
From: M Jared Finder
Subject: Re: A little problem
Date: 
Message-ID: <e9ednYZdwORIK53eRVn-qA@speakeasy.net>
Andreas Thiele wrote:
> "Timofei Shatrov" <····@mail.ru> schrieb im Newsbeitrag
> ·····················@news.readfreenews.net...
> 
>>This is probably a stupid question, but I cannot figure out how to get a
>>value of a variable :)
>>...
> 
> There is a great paper on variable scope by Ron Garret at
> 
> http://www.flownet.com/gat/
> 
> or directly
> 
> http://www.flownet.com/gat/specials.pdf
> 
> CLHS explicitely says "symbol-value cannot access the value of a lexical
> variable.".
> 
> Indeed I somehow wonder about this. Obviously symbol-value doesn't consider
> the environment. I still wonder why this is so and what symbol-value is for?

Because symbol-value is a function, and does not have access to the 
lexical environment in which the symbol is defined.  To make 
symbol-value able to return the lexical value, it would either need to 
take the environment as a parameter or be made into a special form. 
Both seem easy enough to do, and I have no idea why they weren't done.

   -- MJF
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcopssfjisl.fsf@shuttle.math.ntnu.no>
+ M Jared Finder <·····@hpalace.com>:

| Because symbol-value is a function, and does not have access to the
| lexical environment in which the symbol is defined.  To make
| symbol-value able to return the lexical value, it would either need
| to take the environment as a parameter or be made into a special
| form. Both seem easy enough to do, and I have no idea why they
| weren't done.

Perhaps because the lexical environment is essentially gone at
runtime, unless you're running interpreted.  Insisting that you keep
it around would seem to place an undue burden on compiling
implementations.  And for what benefit, exactly?

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Pascal Bourguignon
Subject: Re: A little problem
Date: 
Message-ID: <8764u7f8bs.fsf@thalassa.informatimago.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + M Jared Finder <·····@hpalace.com>:
>
> | Because symbol-value is a function, and does not have access to the
> | lexical environment in which the symbol is defined.  To make
> | symbol-value able to return the lexical value, it would either need
> | to take the environment as a parameter or be made into a special
> | form. Both seem easy enough to do, and I have no idea why they
> | weren't done.
>
> Perhaps because the lexical environment is essentially gone at
> runtime, unless you're running interpreted.  Insisting that you keep
> it around would seem to place an undue burden on compiling
> implementations.  And for what benefit, exactly?

I don't know what benefit it could give, but anyways if it was ever
needed in CL, it's rather easy to implement run-time environments:


(shadow 'let #| later add let*, flet, labels, and macro-let |# )

(defparameter *environment* '())

(defun symbol-value-in-env (symbol env)
  (cond ((null env)
         (if (boundp symbol)
             (values (symbol-value symbol) t)
             (values nil nil)))
        ((null (car env))
         (symbol-value-in-env symbol (cdr env)))
        (t
         (let ((ass (assoc symbol (car env) :test (function eq))))
           (if ass
               (values (funcall (second ass)) t)
               (symbol-value-in-env symbol (cdr env)))))))

(defun (setf symbol-value-in-env) (value symbol env)
  (cond ((null env)
         (if (boundp symbol)
             (setf (symbol-value symbol) value)
             (progn (warn "Creating a global variable ~A" symbol)
                    (setf (symbol-value symbol) value))))
        ((null (car env))
         (setf (symbol-value-in-env symbol (cdr env)) value))
        (t
         (let ((ass (assoc symbol (car env) :test (function eq))))
           (if ass
               (funcall (third ass) value)
               (setf (symbol-value-in-env symbol (cdr env)) value))))))


(defmacro let (bindings &body body)
  `(cl:let ,bindings
     (cl:let ((*environment*
               (cons
                ,(cons
                  'list
                  (mapcar
                   (lambda (binding)
                     (cl:let ((var (if (symbolp binding) binding (car binding)))
                              (value (gensym)))
                       `(list ',var
                             (lambda () ,var)
                             (lambda (,value) (setf ,var ,value)))))
                   bindings))
                *environment*)))
       ,@body)))


(defun incr-in-env (var env)
  (incf (symbol-value-in-env var env)))

(defparameter saved-env 
  (let ((x 'y)(y 42))
    (print `(y = ,(symbol-value-in-env 'y *environment*)))
    (print `(y = ,(symbol-value-in-env x  *environment*)))
    (incr-in-env 'y *environment*)
    (print `(y = ,(symbol-value-in-env 'y *environment*)))
    (print `(y = ,(symbol-value-in-env x  *environment*)))
    (let ((old-env *environment*)
          (y 4))
      (print `(top y = ,(symbol-value-in-env 'y nil)))
      (print `(old y = ,(symbol-value-in-env 'y old-env)))
      (print `(new y = ,(symbol-value-in-env 'y *environment*)))
      (incr-in-env 'y *environment*)
      (print `(top y = ,(symbol-value-in-env 'y nil)))
      (print `(old y = ,(symbol-value-in-env 'y old-env)))
      (print `(new y = ,(symbol-value-in-env 'y *environment*)))
      (incr-in-env 'y old-env)
      (print `(top y = ,(symbol-value-in-env 'y nil)))
      (print `(old y = ,(symbol-value-in-env 'y old-env)))
      (print `(new y = ,(symbol-value-in-env 'y *environment*)))
      (setf (symbol-value-in-env 'y nil) 0)
      (incr-in-env 'y nil)
      (print `(top y = ,(symbol-value-in-env 'y nil)))
      (print `(old y = ,(symbol-value-in-env 'y old-env)))
      (print `(new y = ,(symbol-value-in-env 'y *environment*)))
      *environment*)))

(print `(saved y = ,(symbol-value-in-env 'y saved-env)))
(print `(saved x = ,(symbol-value-in-env 'x saved-env)))

(dolist (env saved-env)
  (terpri)(princ "----")
  (print (mapcar (lambda (bind) (list (first bind) (funcall (second bind))))
          env)))

---> 

[48]> 
(Y = 42) 
(Y = 42) 
(Y = 43) 
(Y = 43) 
(TOP Y = NIL) 
(OLD Y = 43) 
(NEW Y = 4) 
(TOP Y = NIL) 
(OLD Y = 43) 
(NEW Y = 5) 
(TOP Y = NIL) 
(OLD Y = 44) 
(NEW Y = 5) 
WARNING: Creating a global variable Y
(TOP Y = 1) 
(OLD Y = 44) 
(NEW Y = 5) 
SAVED-ENV
[49]> 
(SAVED Y = 5) 
(SAVED Y = 5)
[50]> 
(SAVED X = Y) 
(SAVED X = Y)
[51]> 
----
((OLD-ENV
  (((X #<FUNCTION :LAMBDA NIL X> #<FUNCTION :LAMBDA (#:G4611) (SETF X #:G4611)>)
    (Y #<FUNCTION :LAMBDA NIL Y>
     #<FUNCTION :LAMBDA (#:G4612) (SETF Y #:G4612)>))))
 (Y 5)) 
----
((X Y) (Y 44)) 
NIL
[52]> y
1
[53]> (symbol-value-in-env 'y saved-env)
2 ;
T
[54]> (symbol-value-in-env 'y (cdr saved-env))
44 ;
T

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You're always typing.
Well, let's see you ignore my
sitting on your hands.
From: Marco Baringer
Subject: Re: A little problem
Date: 
Message-ID: <m264u7qe1h.fsf@soma.local>
Pascal Bourguignon <····@mouse-potato.com> writes:

> I don't know what benefit it could give, but anyways if it was ever
> needed in CL, it's rather easy to implement run-time environments:

It was once, rather recently, needed to integrate 'regular' common
lisp code with a lisp interpreter written in lisp and embedded into
lisp code.

ARNESI> (defmacro symbol-value* (symbol &environment environment)
           (with-unique-names (vars var)
             `(let* ((,vars (list ,@(mapcar (lambda (name)
                                              `(cons ',name 
                                                     (lambda () ,name)))
                                            (lexical-variables environment))))
                     (,var (assoc ,symbol ,vars)))
                (if ,var
                    (funcall (cdr ,var))
                    (error "No variable named ~S in environment ~S." 
                           ',symbol ',environment)))))
SYMBOL-VALUE*
ARNESI> (defun foo (sym)
          (let ((a 0)
                (b 1))
            (symbol-value* sym)))
FOO
ARNESI> (foo 'a)
0
ARNESI> (foo 'b)
1

[plug: the trick to this is the function lexical-variables. an
implementation of this function is available for openmcl, sbcl, cmucl
and clisp in the arnesi library]

-- 
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
	-Leonard Cohen
From: Pascal Bourguignon
Subject: Re: A little problem
Date: 
Message-ID: <87acjjfag8.fsf@thalassa.informatimago.com>
M Jared Finder <·····@hpalace.com> writes:
> Because symbol-value is a function, and does not have access to the
> lexical environment in which the symbol is defined.  To make
> symbol-value able to return the lexical value, it would either need to
> take the environment as a parameter or be made into a special
> form. Both seem easy enough to do, and I have no idea why they weren't
> done.

Because CL let the implementations forget the environment at run time.
Note how the only place where an environment is accessible is in macros.

In CL, environments are compilation time (and macro-expansion time) only.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: Ron Garret
Subject: Re: A little problem
Date: 
Message-ID: <rNOSPAMon-5B7F09.10122115082005@news.gha.chartermi.net>
In article <···············@news.t-online.com>,
 "Andreas Thiele" <······@nospam.com> wrote:

> "Timofei Shatrov" <····@mail.ru> schrieb im Newsbeitrag
> ·····················@news.readfreenews.net...
> >
> > This is probably a stupid question, but I cannot figure out how to get a
> > value of a variable :)
> > ...
> 
> There is a great paper on variable scope by Ron Garret at
> 
> http://www.flownet.com/gat/
> 
> or directly
> 
> http://www.flownet.com/gat/specials.pdf
> 
> CLHS explicitely says "symbol-value cannot access the value of a lexical
> variable.".
> 
> Indeed I somehow wonder about this. Obviously symbol-value doesn't consider
> the environment. I still wonder why this is so and what symbol-value is for?

It's designed to confuse newbies.

(Seriously, symbol-value is for getting the value of a variable whose 
identity is not known until run time.  But, like EVAL (symbol-value is 
just a domain-limited EVAL), using it is almost always an indication 
that you are doing something wrong.)

rg
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86ll33bipd.fsf@drjekyll.mkbuelow.net>
"Andreas Thiele" <······@nospam.com> writes:

>Indeed I somehow wonder about this. Obviously symbol-value doesn't consider
>the environment. I still wonder why this is so and what symbol-value is for?

Because there is no symbol "X" connected with the lexical variable
anymore, once it is compiled (since the compiler has resolved the
lexical variable into a memory address; in contrast to the special
variable, which is an interned symbol).

You'll probably want to do the following, to get dynamic lookup:

(proclaim '(special x))
(setf x 1)
(setf y 'x)
(let ((x 42)) (symbol-value y))

which works as expected.

mkb.
From: Andreas Thiele
Subject: Re: A little problem
Date: 
Message-ID: <ddprrl$lpc$05$1@news.t-online.com>
"Matthias Buelow" <···@incubus.de> schrieb im Newsbeitrag
···················@drjekyll.mkbuelow.net...
> "Andreas Thiele" <······@nospam.com> writes:
>
> >Indeed I somehow wonder about this. Obviously symbol-value doesn't
consider
> >the environment. I still wonder why this is so and what symbol-value is
for?
>
> Because there is no symbol "X" connected with the lexical variable
> anymore, once it is compiled (since the compiler has resolved the
> lexical variable into a memory address; in contrast to the special
> variable, which is an interned symbol).
> ...

I did not compile things, just ran it at the REPL. Obviously I can use
symbols within the let. I am quite sure

(let ((x 42)) x)

will return 42, the value of the variable denoted by the symbol X.

> You'll probably want to do the following, to get dynamic lookup:
>
> (proclaim '(special x))
> (setf x 1)
> (setf y 'x)
> (let ((x 42)) (symbol-value y))
>
> which works as expected.
> ...

Yes, as I said, this is what CLHS requires.

Most probably it is my (mis)understanding of environments. I think the
symbol X within the LET only lives in the LETs lexical environment. Right?
Or is it only the binding which lives in the lexical environment? Why
doesn't symbol-value consider the lexical environment at all? There should
be a special reason? Perhaps because symbol-value needs eval as an extra
level of evaluation on it's argument (which doesn't consider environments)?

Andreas
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <86d5ofbh7h.fsf@drjekyll.mkbuelow.net>
"Andreas Thiele" <······@nospam.com> writes:

>Most probably it is my (mis)understanding of environments. I think the
>symbol X within the LET only lives in the LETs lexical environment. Right?
>Or is it only the binding which lives in the lexical environment? Why
>doesn't symbol-value consider the lexical environment at all? There should
>be a special reason? Perhaps because symbol-value needs eval as an extra
>level of evaluation on it's argument (which doesn't consider environments)?

Because the lexical environment might be effectively gone, when the
code is compiled (it's compiled into direct memory references, with no
symbols left, so no symbol lookup can happen). That might not be true
of interpreted code but it is most surely of compiled code. You need
to declare the variable special (with defvar, or, if you use setq,
with explicit declarations) so the compiler won't reduce the inner "x"
into a simple memory reference but into an environment lookup.

mkb.
From: Andreas Thiele
Subject: Re: A little problem
Date: 
Message-ID: <ddpvbo$7m9$00$1@news.t-online.com>
"Matthias Buelow" <···@incubus.de> schrieb im Newsbeitrag
> ...
> Because the lexical environment might be effectively gone, when the
> code is compiled (it's compiled into direct memory references, with no
> symbols left, so no symbol lookup can happen).
> ...

But the call to SYMBOL-VALUE is within the LET, thus at a moment when the
lexical environment is alive?

I can't imagine that this is a compilation issue. My Lisp (LispWorks)
doesn't behave different in regard to compiling these lines.

Let me explain what I mean. If we would not have SYMBOL-VALUE, we could
write an own version like

(defun symbol-value1 (arg) (eval arg))

Now this behaves like the built in SYMBOL-VALUE. LispWorks session:

CL-USER 9 > (setq x 1)
1

CL-USER 10 > (symbol-value1 'x)
1

CL-USER 11 > (setq y 'x)
X

CL-USER 12 > (symbol-value1 y)
1

CL-USER 13 > (let ((x 42)) (symbol-value1 y))
1

This is what I meant. SYMBOL-VALUE has to evaluate it's argument. EVAL
executes in the nil lexical environment (or maybe 'toplevel environment'),
thus SYMBOL-VALUE can only access 'global' symbols.

Now we might invent a new SYMBOL-VALUE2 macro, which provides access to the
lexical X.

(defmacro symbol-value2 (arg/s)
  (if (consp arg/s)
    `(identity ,(cadr arg/s))
    `(identity ,(eval arg/s))))

With this we'd get

CL-USER 38 > (let ((x 49)) (symbol-value2 y))
49

but unfortunately also

CL-USER 39 > (let ((z 49) (y 'z)) (symbol-value2 y))
1

because Y still needs the second level of evaluation, and I ran out of
creative ideas :))


Andreas
From: Matthias Buelow
Subject: Re: A little problem
Date: 
Message-ID: <864q9rbd9o.fsf@drjekyll.mkbuelow.net>
"Andreas Thiele" <······@nospam.com> writes:

>This is what I meant. SYMBOL-VALUE has to evaluate it's argument. EVAL
>executes in the nil lexical environment (or maybe 'toplevel environment'),
>thus SYMBOL-VALUE can only access 'global' symbols.

I understand what you're trying to do but symbol-value does not
"evaluate" its argument but most likely (theoretically depending on
the implementation, of course) accesses the value cell directly. The
"symbol" that is the value of Y is nothing but a pointer to the symbol
entry for X in the package where X is interned at the point of Y's
definition, where the symbol is like a structure containing various
slots (name, home package, value, function value, etc.)

>Now we might invent a new SYMBOL-VALUE2 macro, which provides access to the
>lexical X.
>
>(defmacro symbol-value2 (arg/s)
>  (if (consp arg/s)
>    `(identity ,(cadr arg/s))
>    `(identity ,(eval arg/s))))
>
>With this we'd get
>
>CL-USER 38 > (let ((x 49)) (symbol-value2 y))

But that's just macro trickery; you cannot access the symbol of a
lexical variable, in general, because there might be none and you
cannot do it that way anyways, since it's a lexical binding and Y
was set to the X that appears lexically before the let binding.
That is, Y references the outer X, since that was where Y was defined
(and initialized). That's the whole point of lexical variables. What
you want is a dynamic lookup, you can accomplish that by making X
special (either by declaring via defvar/defparameter at the toplevel,
instead of setf), or by explicitly declaring it special.

As has been commented (I didn't know that because I don't use cmucl
often, since it just segfaults on my main machine here), cmucl makes
toplevel bindings established by setq/setf special by default but that
doesn't happen in all other implementations and it doesn't happen when
you run it through the compiler. So to be sure, defvar/defparameter
the variable instead.

mkb.
From: alexander
Subject: Re: A little problem
Date: 
Message-ID: <1124112609.654340.25880@z14g2000cwz.googlegroups.com>
cmucl makes toplevel bindings established by setq/setf special by
default.

Is it possible to change such behaviour ?
From: Thomas A. Russ
Subject: Re: A little problem
Date: 
Message-ID: <ymiacjjf2f8.fsf@sevak.isi.edu>
"alexander" <········@gmail.com> writes:

> 
> cmucl makes toplevel bindings established by setq/setf special by
> default.
> 
> Is it possible to change such behaviour ?

Generally, no.
Such behavior is usually not under user control, although there may be
some setting in CMUCL that doesn't do the proclaim....

But if it were changeable, the only reasonable other option would be to
throw an error since there is no "top-level LEXICAL environment".  You
would be trying to assign to a non-existent variable.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Harald Hanche-Olsen
Subject: Re: A little problem
Date: 
Message-ID: <pcok6inj7gu.fsf@shuttle.math.ntnu.no>
+ ···@sevak.isi.edu (Thomas A. Russ):

| "alexander" <········@gmail.com> writes:
| 
| > 
| > cmucl makes toplevel bindings established by setq/setf special by
| > default.
| > 
| > Is it possible to change such behaviour ?
| 
| Generally, no.
| Such behavior is usually not under user control, although there may be
| some setting in CMUCL that doesn't do the proclaim....

There is.  People have made two references to the CMUCL FAQ in this
thread already.  For good measure, I'll refer to it again, with an URL
and all:

  http://www.cons.org/cmucl/FAQ.html

See question 2.  There isn't even a need to scroll the window, unless
you have a tiny screen.  And before you ask: The variable
ext:*top-level-auto-declare* does have a documentation string.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Christophe Rhodes
Subject: Re: A little problem
Date: 
Message-ID: <sqll33gwda.fsf@cam.ac.uk>
"alexander" <········@gmail.com> writes:

> cmucl makes toplevel bindings established by setq/setf special by
> default.
>
> Is it possible to change such behaviour ?

What, you still haven't read the CMUCL FAQ?

Christophe
From: Pascal Bourguignon
Subject: Re: A little problem
Date: 
Message-ID: <87k6infk30.fsf@thalassa.informatimago.com>
"Andreas Thiele" <······@nospam.com> writes:
> Indeed I somehow wonder about this. Obviously symbol-value doesn't consider
> the environment. I still wonder why this is so and what symbol-value is for?

(defun double-variable (variable)
    (set variable (* 2 (symbol-value variable))))

(let ((variable (gensym)))
  (set variable 5550960)
  (print (symbol-value variable))
  (double-variable variable)
  (print (symbol-value variable)))
  

-- 
"Specifications are for the weak and timid!"
From: Andreas Thiele
Subject: Re: A little problem
Date: 
Message-ID: <ddr32k$hi0$00$1@news.t-online.com>
"Pascal Bourguignon" <····@mouse-potato.com> schrieb im Newsbeitrag
···················@thalassa.informatimago.com...
> "Andreas Thiele" <······@nospam.com> writes:
> > Indeed I somehow wonder about this. Obviously symbol-value doesn't consider
> > the environment. I still wonder why this is so and what symbol-value is for?
>
> (defun double-variable (variable)
>     (set variable (* 2 (symbol-value variable))))
>
> (let ((variable (gensym)))
>   (set variable 5550960)
>   (print (symbol-value variable))
>   (double-variable variable)
>   (print (symbol-value variable)))
>
>
> --
> "Specifications are for the weak and timid!"

I see, thanks.
From: Edi Weitz
Subject: Re: A little problem
Date: 
Message-ID: <u1x4v7ayv.fsf@agharta.de>
On Mon, 15 Aug 2005 08:36:39 GMT, ····@mail.ru (Timofei Shatrov) wrote:

> This is probably a stupid question, but I cannot figure out how to
> get a value of a variable :) Suppose the value of y is x and the
> value of x is 42. What do I need to do with y to get 42?
>
> symbol-value doesn't work when the value of x is lexically scoped.
>
> (setf x 1) => 1
> (setf y 'x) => X
> (let ((x 42)) (symbol-value y)) => 1

Try to figure out how to do what you want in C.  As others have said,
Lisp is not Perl or PHP.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: John
Subject: Re: A little problem
Date: 
Message-ID: <slrndg1bih.kch.4UenKXib@mailinator.com>
On 2005-08-15, Timofei Shatrov <····@mail.ru> wrote:
>  This is probably a stupid question, but I cannot figure out how to get a
>  value of a variable :) Suppose the value of y is x and the value of x is
>  42. What do I need to do with y to get 42?
> 
>  symbol-value doesn't work when the value of x is lexically scoped.
> 
>  (setf x 1) => 1
>  (setf y 'x) => X
>  (let ((x 42)) (symbol-value y)) => 1

Various quotes from the hyperspec page for symbol-value:

  "SYMBOL-VALUE cannot see lexical variables"

  "symbol-value cannot access the value of a lexical variable"

Additionally the same page in the description says:

  "Accesses the symbol's value cell."

And if you follow the link for "value cell" you get:

  "The place which holds the value, if any, of the dynamic variable named
   by that symbol, and which is accessed by symbol-value.

In your exaple, x is lexically scoped, not dynamic.
From: Timofei Shatrov
Subject: Re: A little problem
Date: 
Message-ID: <4300d07f.12383288@news.readfreenews.net>
On Mon, 15 Aug 2005 15:01:37 GMT, John <········@mailinator.com> tried
to confuse everyone with this message:

>On 2005-08-15, Timofei Shatrov <····@mail.ru> wrote:
>>  This is probably a stupid question, but I cannot figure out how to get a
>>  value of a variable :) Suppose the value of y is x and the value of x is
>>  42. What do I need to do with y to get 42?
>> 
>>  symbol-value doesn't work when the value of x is lexically scoped.
>> 
>>  (setf x 1) => 1
>>  (setf y 'x) => X
>>  (let ((x 42)) (symbol-value y)) => 1
>
>Various quotes from the hyperspec page for symbol-value:
>
><snip>

Well, I can read Hyperspec, thank-you-very-much. One deliberately
non-working example and everyone assumes you're a n00b (not that I'm
not). If I didn't know why it didn't work I'd probably introduced yet
another subtle bug in my project and didn't post the original message. I
still can't tell from the above discussion whether it's possible to
substitute symbol-value in the above example to something that works.

-- 
|a\o/r|,-------------.,---------- Timofei Shatrov aka Grue ------------.
| m"a ||FC AMKAR PERM|| mail: grue at mail.ru  http://grue3.tripod.com |
|  k  ||  PWNZ J00   || Kingdom of Loathing: Grue3 lvl 18 Seal Clubber |
`-----'`-------------'`-------------------------------------------[4*72]
From: Pascal Bourguignon
Subject: Re: A little problem
Date: 
Message-ID: <87wtmndnd6.fsf@thalassa.informatimago.com>
····@mail.ru (Timofei Shatrov) writes:

> On Mon, 15 Aug 2005 15:01:37 GMT, John <········@mailinator.com> tried
> to confuse everyone with this message:
>
>>On 2005-08-15, Timofei Shatrov <····@mail.ru> wrote:
>>>  This is probably a stupid question, but I cannot figure out how to get a
>>>  value of a variable :) Suppose the value of y is x and the value of x is
>>>  42. What do I need to do with y to get 42?
>>> 
>>>  symbol-value doesn't work when the value of x is lexically scoped.
>>> 
>>>  (setf x 1) => 1
>>>  (setf y 'x) => X
>>>  (let ((x 42)) (symbol-value y)) => 1
>>
>>Various quotes from the hyperspec page for symbol-value:
>>
>><snip>
>
> Well, I can read Hyperspec, thank-you-very-much. One deliberately
> non-working example and everyone assumes you're a n00b (not that I'm
> not). If I didn't know why it didn't work I'd probably introduced yet
> another subtle bug in my project and didn't post the original message. I
> still can't tell from the above discussion whether it's possible to
> substitute symbol-value in the above example to something that works.

Then why did I spent 30 minutes writing my run-time environment LET macro?  

(By the way, I missed two cl: in symbol-value-in-env and the (setf
symbol-value-in-env) so here it is again:



(shadow 'let #| later add let*, flet, labels, and macro-let |# )

(defparameter *environment* '())

(defun symbol-value-in-env (symbol env)
  (cond ((null env)
         (if (boundp symbol)
             (values (symbol-value symbol) t)
             (values nil nil)))
        ((null (car env))
         (symbol-value-in-env symbol (cdr env)))
        (t
         (cl:let ((ass (assoc symbol (car env) :test (function eq))))
           (if ass
               (values (funcall (second ass)) t)
               (symbol-value-in-env symbol (cdr env)))))))

(defun (setf symbol-value-in-env) (value symbol env)
  (cond ((null env)
         (if (boundp symbol)
             (setf (symbol-value symbol) value)
             (progn (warn "Creating a global variable ~A" symbol)
                    (setf (symbol-value symbol) value))))
        ((null (car env))
         (setf (symbol-value-in-env symbol (cdr env)) value))
        (t
         (cl:let ((ass (assoc symbol (car env) :test (function eq))))
           (if ass
               (funcall (third ass) value)
               (setf (symbol-value-in-env symbol (cdr env)) value))))))


(defmacro let (bindings &body body)
  `(cl:let ,bindings
     (cl:let ((*environment*
               (cons
                ,(cons
                  'list
                  (mapcar
                   (lambda (binding)
                     (cl:let ((var (if (symbolp binding) binding (car binding)))
                              (value (gensym)))
                       `(list ',var
                              (lambda () ,var)
                              (lambda (,value) (setf ,var ,value)))))
                   bindings))
                *environment*)))
       ,@body)))


[66]> (setf x 1)
1
[67]> (setf y 'x)
X
[68]> (let ((x 42)) (symbol-value y)) 
1  ; As specified!
[69]> (let ((x 42)) (symbol-value-in-env y *environment*))
42 ; Get what you want!
T


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"
From: Timofei Shatrov
Subject: Re: A little problem
Date: 
Message-ID: <4300ef94.20342032@news.readfreenews.net>
On Mon, 15 Aug 2005 21:13:57 +0200, Pascal Bourguignon
<····@mouse-potato.com> tried to confuse everyone with this message:

>Then why did I spent 30 minutes writing my run-time environment LET macro?  

I received your post too late. I hoped a more elegant solution exists,
but it seems my approach is un-lispy in its core so I'll have to trim it
in accordance with lispist lifestyle [1].

[1] http://tinyurl.com/7bt3x

-- 
|a\o/r|,-------------.,---------- Timofei Shatrov aka Grue ------------.
| m"a ||FC AMKAR PERM|| mail: grue at mail.ru  http://grue3.tripod.com |
|  k  ||  PWNZ J00   || Kingdom of Loathing: Grue3 lvl 18 Seal Clubber |
`-----'`-------------'`-------------------------------------------[4*72]
From: Robert Uhl
Subject: Re: A little problem
Date: 
Message-ID: <m3psse7tbn.fsf@4dv.net>
····@mail.ru (Timofei Shatrov) writes:
>
> I hoped a more elegant solution exists, but it seems my approach is
> un-lispy in its core so I'll have to trim it in accordance with
> lispist lifestyle.

*grin*

Seriously, what exactly are you trying to do?  I've a hunch that you're
used to Perl and are trying to pull off the sort of thing which is often
necessary therein but which could be done more elegantly in idiomatic
Lisp, possibly with a macro, or possibly with some altogether different
facility.

Given the brains in the group, I imagine a simple problem description
could get you an answer pretty easily.

OTOH, perhaps you're just playing with the language to learn things--in
which case, you've now learnt the difference between interpreted and
compiled code:-)

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
The Metric System is an unfortunate combination of unergonomic measures
locked into a rigid structure whereby form becomes dominant over fact
and does not allow any departure from itself for practicalities.
                                        --DGSB, on French units
From: Andreas Thiele
Subject: Re: A little problem
Date: 
Message-ID: <ddr43k$gc3$01$1@news.t-online.com>
"Pascal Bourguignon" <····@mouse-potato.com> schrieb im Newsbeitrag
···················@thalassa.informatimago.com...
> ...
> Then why did I spent 30 minutes writing my run-time environment LET macro?
> ...

I read this too and I'll digest your code right now :))

Andreas
From: Ivan Boldyrev
Subject: Re: A little problem
Date: 
Message-ID: <5dmqt2-5s4.ln1@ibhome.cgitftp.uiggm.nsc.ru>
On 9203 day of my life Timofei Shatrov wrote:
> Well, I can read Hyperspec, thank-you-very-much. One deliberately
> non-working example and everyone assumes you're a n00b (not that I'm
> not). If I didn't know why it didn't work I'd probably introduced yet
> another subtle bug in my project and didn't post the original message. I
> still can't tell from the above discussion whether it's possible to
> substitute symbol-value in the above example to something that works.

Just declare x to be special variable with (declare (special x))
inside let, or (defvar x) at toplevel, � ���� ���� ����� �������� �
������������.

� ������, ������������� setf/setq �� ������������� � �������
let/defvar/defparameter ���������� -- undefined behavior, �� �������
��, ����������, � ��������.  � ������ ��� � ����� Hyperspec �ݣ ���.
��� �����, ��� ���������� ������ 80-� �����.

-- 
Ivan Boldyrev

        Outlook has performed an illegal operation and will be shut down.
        If the problem persists, contact the program vendor.
From: Pascal Costanza
Subject: Re: A little problem
Date: 
Message-ID: <3mc5j3F15ouu5U1@individual.net>
Timofei Shatrov wrote:
> This is probably a stupid question, but I cannot figure out how to get a
> value of a variable :) Suppose the value of y is x and the value of x is
> 42. What do I need to do with y to get 42?
> 
> symbol-value doesn't work when the value of x is lexically scoped.
> 
> (setf x 1) => 1
> (setf y 'x) => X
> (let ((x 42)) (symbol-value y)) => 1

ANSI Common Lisp doesn't define any operator that lets you access 
lexical variables (or other bindings) at runtime. This is in order to 
allow for optimizations that otherwise couldn't be performed. 
Essentially, without such operators, you can compile all accesses to 
lexical variables by a base address + offset access scheme, and even 
inline values when you can prove that no changes occur, etc. pp.

I am not aware of any Common Lisp implementation that provides 
first-class access to lexical variables as an add-on feature, but 
OpenLisp does, which is an implementation of ISLISP. (ISLISP in turn is 
more or less a subset of Common Lisp.)

Here is a transcript:

? (defglobal x 1)
= x
? (defglobal y 'x)
= y
? (let ((x 42))
     (eval y (the-environment)))
= 42
? (defglobal env
     (let ((x 42))
       (the-environment)))
= env
? (eval y env)
= 42

First-class lexical environments also exist in some Scheme 
implementations. For example, they can be useful to play around with 
very simple object systems:

(defun make-point (x y)
   (the-environment))

(let ((point (make-point 10 20)))
   (print (eval 'x point))
   (print (eval 'y point)))

is not unlike:

(let ((point (make-instance 'point :x 10 :y 20)))
   (print (slot-value point 'x))
   (print (slot-value point 'y)))


However, in OpenLisp that simple example already seems to fail...


Pascal

-- 
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++