From: Software Scavenger
Subject: emacs let
Date: 
Message-ID: <a6789134.0109051146.38aa178f@posting.google.com>
I read somewhere that in emacs lisp, let binds variables globally. 
But that doesn't make sense to me.  How does it bind them globally? 
Does it just clobber the global value of the variable and replace it
with a new value?  What's the point of doing it that way?  The let
form establishes a context, and it doesn't make sense not to take
advantage of that context by at least undoing the change at the exit
from the context.  Would someone please explain it.

From: Barry Margolin
Subject: Re: emacs let
Date: 
Message-ID: <Glvl7.47$nH5.496@burlma1-snr2>
In article <····························@posting.google.com>,
Software Scavenger <··········@mailandnews.com> wrote:
>I read somewhere that in emacs lisp, let binds variables globally. 
>But that doesn't make sense to me.  How does it bind them globally? 
>Does it just clobber the global value of the variable and replace it
>with a new value?  What's the point of doing it that way?  The let
>form establishes a context, and it doesn't make sense not to take
>advantage of that context by at least undoing the change at the exit
>from the context.  Would someone please explain it.

GNU Emacs Lisp uses dynamic scoping, as if every variable were declared
special.  When a variable is bound, its value cell is clobbered and the old
value is saved on the stack.

The reason it's done this way is because it's extremely simple to
implement.  To look up a variable's value you just look in the value cell
of the variable, rather than searching environments.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Hallvard B Furuseth
Subject: Re: emacs let
Date: 
Message-ID: <HBF.20010905qih6@bombur.uio.no>
Barry Margolin <······@genuity.net> writes:
> GNU Emacs Lisp uses dynamic scoping, as if every variable were declared
> special.  When a variable is bound, its value cell is clobbered and the old
> value is saved on the stack.

Well, emacs does have a poor man's context: Variables can be declared
buffer-local.  So when you switch buffer, references to global variables
are forwarded to the buffer-local versions, or something.

In case you are wondering, this _does_ confuse emacs if you do things
like
  (let ((some-local-variable 'foo))
    (set-buffer "bar"))
which leaves some-local-variable = 'foo.  Still, it usually works well
enough.

-- 
Hallvard
From: Deepak Goel
Subject: Re: emacs let
Date: 
Message-ID: <ap3ofop3xn0.fsf@erie.umd.edu>
> I read somewhere that in emacs lisp, let binds variables globally. 
> But that doesn't make sense to me.  How does it bind them globally? 



	
(Let ((x 1)) x)

X

errors: Symbol definition void..

So in some sense, it is not defined globally..  But i dunno too much
about all this..
From: Kent M Pitman
Subject: Re: emacs let
Date: 
Message-ID: <sfwofopxb01.fsf@world.std.com>
Deepak Goel <·····@glue.umd.edu> writes:

> > I read somewhere that in emacs lisp, let binds variables globally. 
> > But that doesn't make sense to me.  How does it bind them globally? 
> 	
> (Let ((x 1)) x)
> 
> X
> 
> errors: Symbol definition void..
> 
> So in some sense, it is not defined globally..  But i dunno too much
> about all this..

Its scope is indefinite.

(defun foo () x)

(let ((x 1)) (foo)) => 1

The reason for this is partly (as Barry says) that it's simple to implement
the interpreter for this.

But also, in defense of early Lisps and of RMS who clung to the old way when
CL came along, it trades off easy debuggability for massive extensibility.

That is, any function which references a free variable might be affected by
anything higher on the stack, which makes sometimes for a debugging nightmare.
But it also means that any function that wants to customize the effect of
a callee can do so straightforwardly and any function that wants to be 
sensitive to existing dynamic bindings can do so easily.  In a system like
Emacs which is all about custom behavior, there is more defensibility to this
choice than there might be in a system chosen wholly at random.
From: Roger Corman
Subject: Re: emacs let / rambling on about special variables
Date: 
Message-ID: <3b970c64.192963907@news.callatg.com>
On Thu, 6 Sep 2001 03:18:38 GMT, Kent M Pitman <······@world.std.com> wrote:

>Deepak Goel <·····@glue.umd.edu> writes:
>
>> > I read somewhere that in emacs lisp, let binds variables globally. 
>> > But that doesn't make sense to me.  How does it bind them globally? 
>> 	
...
>(let ((x 1)) (foo)) => 1
>
>The reason for this is partly (as Barry says) that it's simple to implement
>the interpreter for this.
>
>But also, in defense of early Lisps and of RMS who clung to the old way when
>CL came along, it trades off easy debuggability for massive extensibility.
>
>That is, any function which references a free variable might be affected by
>anything higher on the stack, which makes sometimes for a debugging nightmare.
>But it also means that any function that wants to customize the effect of
>a callee can do so straightforwardly and any function that wants to be 
>sensitive to existing dynamic bindings can do so easily.  In a system like
>Emacs which is all about custom behavior, there is more defensibility to this
>choice than there might be in a system chosen wholly at random.

I can't resist a little rambling here...

And of course these variables still live on in Common Lisp as special variables.
I think these are one of the 7 wonders of the ancient world of Lisp. I love
special variables. I don't use them often--only when necessary.  :-)
But they are one of the things that really sets Lisp, including Common Lisp,
apart from so many other languages. Yes, people quibble about the way they
are kind of glued into the syntax, and a source of confusion (especially
to newbies). But, they are so elegant, and powerful. The ability to affect
behavior far down the call stack means that you don't have to pass extra
arguments that cloud the main purpose of the code.

I found special variables really get fun when you combine them with
multi-threading. Although non-standard, most Common Lisps do
special variable binding on a per-thread basis, which essentially gives
you per-thread global values to play with. Just do some defvars, bind
them in your main thread function, and use them wherever you want.
Elegant, useful and efficient. When I programmed in C and C++ I learned
that global variables are BAD. However, one of the main reasons they
are bad is that they are not thread-safe.With that problem removed, the
only thing bad about them is global name space pollution (and keeping
track of them) which can be solved with packages or namespaces.
From a performance perspective, global variables are sometimes
faster to use than passing extra parameters around. Special variables
are better than C-style globals because they can be bound, and the
lifespan of that binding is well-defined. Since it can be seen from any
function, while bound, it allows the same efficiencies of C global variables.

As an example, I have written many parsers. I typically prefer to do
hand-written recursive descent parsers, because they are easy to
write, maintain, and extend. You can easily glom on alternate 
syntaxes and do context-dependent stuff. They are easy for other
programmers, even those not real strong on parsing, to figure out
well enough to make small changes. In any recursive descent
parser you tend to have 100s of small functions which all share
some common data structures: input stream, parse tree, lexer, etc.
I have found the performance of these parsers is relative to
the number of parameters being passed around between all those
functions. By far the best performance is to make those shared
data global. With special variables this is easy, and does not
compromise thread safety. And any nested code can implement
context-dependent changes by simply rebinding modified versions
of those shared variables.

I know of no other language which makes this type of thing so easy
(well I only know so many languages--I am sure there are some).
I do know that per-thread variables are a pain in Java and C++, very
clumsy. (They are standard in Java, but implementation-dependent in C++).

Roger
From: Espen Vestre
Subject: Re: emacs let / rambling on about special variables
Date: 
Message-ID: <w6r8tkkam4.fsf@wallace.ws.nextra.no>
·····@corman.net (Roger Corman) writes:

> I found special variables really get fun when you combine them with
> multi-threading. 

I work on a fairly large system with several multi-threading server
applications, and I whole-heartedly agree with you. Special variables
can be extremely useful sometimes, and the fact that they are thread-
specific has made it possible for us to make _huge_ enhancements of
our code with almost no rewrite necessary - we only had to add a few 
lines of code that bind special variables at the right places. In
one specific case, we could even use an :around-method to do the
thread specific binding, so we could provide the enhancement as an
optional add-on.
-- 
  (espen)
From: Tim Bradshaw
Subject: Re: emacs let / rambling on about special variables
Date: 
Message-ID: <ey3itewn0oj.fsf@cley.com>
* Espen Vestre wrote:

> I work on a fairly large system with several multi-threading server
> applications, and I whole-heartedly agree with you. Special variables
> can be extremely useful sometimes, and the fact that they are thread-
> specific has made it possible for us to make _huge_ enhancements of
> our code with almost no rewrite necessary - we only had to add a few 
> lines of code that bind special variables at the right places. In
> one specific case, we could even use an :around-method to do the
> thread specific binding, so we could provide the enhancement as an
> optional add-on.

Yes, I love this trick.  I worked recently on a system (the one with
the horrid THEN / ELSE syntax) which made use of special variables to
do just this kind of state-for-a-particular-computation thing.  What
we ended up with is what I think is an under-used trick - non-global
specials together with a syntax for them.  What happened was, at the
top level of the computation you'd say something like this:

        (let ((%error-messages% '())
              (%current-state% ':start))
          (declare (special %error-messages% %current-state%))
          (call-next-method))

The trick being that, because the variables defined are not global, if
you write some function (called within this dynamic scope) which does
this:

        (defun grib (...)
          ... %error-messages% ...)

then this gets a compiler warning, because there is intentionally no
global special declaration for %ERROR-MESSAGES%.  Alternatively if you
are using %ERROR-MESSAGES% as a normal, lexically-bound variable that
just works right.  What you have to say to get at the special state
variables is

        (defun grob (...)
          (declare (special %error-messages% %current-state%))
          ... %error-messages% ...)

This is nice, because you get the benefit of special variables without
the having-to-worry-about-names all the time - I don't think we used
the % convention, which I just made up here in fact.

Of course rather than all these obscure declarations we had a pair of
macros so this code looked like:

        (with-error-state ((%error-messages% '()) (%current-state% ':start))
          ...)

        (with-access-to-error-state (%error-messages%)
          ...)

and in fact these are defined by a macro-defining-macro which lets you
define these kinds of thing, and I think will check that you are using
only the variables you said you would &c &c.  This made the code quite
easyt to read because there was effectively a big note at the start of
it saying `I'm using these state variables here'. The macro-defining
macro also gives you a convenient place to document what the dynamic
state variables are & so on. There's a cleaned-up version of this on
www.tfeb.org somewhere.

I actually wrote all this because I was finding it hard to keep track
of the specials that already existed in the code so I wanted to
formalise this notion of a dynamic state so I could read it.

This would have been hard to do in any other language I know: the
special variable bit is pretty unique to Lisp, the syntax to make it
clear what is going on to the reader is pretty unique to Lisp, finally
the metasyntax which lets you *define* these syntaxes in your program
is just completely Lisp.

--tim
From: Thomas F. Burdick
Subject: Re: emacs let / rambling on about special variables
Date: 
Message-ID: <xcv1ylkp08a.fsf@conquest.OCF.Berkeley.EDU>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> ·····@corman.net (Roger Corman) writes:
> 
> > I found special variables really get fun when you combine them with
> > multi-threading. 
> 
> I work on a fairly large system with several multi-threading server
> applications, and I whole-heartedly agree with you. Special variables
> can be extremely useful sometimes, and the fact that they are thread-
> specific has made it possible for us to make _huge_ enhancements of
> our code with almost no rewrite necessary - we only had to add a few 
> lines of code that bind special variables at the right places. In
> one specific case, we could even use an :around-method to do the
> thread specific binding, so we could provide the enhancement as an
> optional add-on.

And this alone is more than enough justification for Elisp to be
dynamically scoped (which is something a lot of people advocating
moving Emacs to scheme understand but don't like to admit).  In normal
Lisp code, this is a powerful tool that can be used sometimes.  In
Emacs, adding :around advice that binds variables is one of its great
strengths -- it allows you to extend extensions with the same ease
that you can extend the system itself (actually easier).  And I've not
had too much trouble debugging in this environment, I think because
the whole debugging infrastructure was designed with this knowledge.
From: Reini Urban
Subject: Re: emacs let / rambling on about special variables
Date: 
Message-ID: <9fdb4c8c.0109080519.644952a9@posting.google.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote in message news:<···············@conquest.OCF.Berkeley.EDU>...
> Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:
> 
> > ·····@corman.net (Roger Corman) writes:
> > 
> > > I found special variables really get fun when you combine them with
> > > multi-threading. 
> > 
> > I work on a fairly large system with several multi-threading server
> > applications, and I whole-heartedly agree with you. Special variables
> > can be extremely useful sometimes, and the fact that they are thread-
> > specific has made it possible for us to make _huge_ enhancements of
> > our code with almost no rewrite necessary - we only had to add a few 
> > lines of code that bind special variables at the right places. In
> > one specific case, we could even use an :around-method to do the
> > thread specific binding, so we could provide the enhancement as an
> > optional add-on.
> 
> And this alone is more than enough justification for Elisp to be
> dynamically scoped (which is something a lot of people advocating
> moving Emacs to scheme understand but don't like to admit).  In normal
> Lisp code, this is a powerful tool that can be used sometimes.  In
> Emacs, adding :around advice that binds variables is one of its great
> strengths -- it allows you to extend extensions with the same ease
> that you can extend the system itself (actually easier).  And I've not
> had too much trouble debugging in this environment, I think because
> the whole debugging infrastructure was designed with this knowledge.

But event-driven GUI with callbacks and object in states is a nightmare 
with dynamic vars. lexvars are a must.
similar for autolisp. that's why both of them still have no reasonable 
(only horrible) GUI's.
From: ···@itasoftware.com
Subject: Re: emacs let
Date: 
Message-ID: <r8tkifbo.fsf@itasoftware.com>
Deepak Goel <·····@glue.umd.edu> writes:

> > I read somewhere that in emacs lisp, let binds variables globally. 
> > But that doesn't make sense to me.  How does it bind them globally? 
> 
> 
> 
> 	
> (Let ((x 1)) x)
> 
> X
> 
> errors: Symbol definition void..
> 
> So in some sense, it is not defined globally..  But i dunno too much
> about all this..

Careful, Emacs lisp is case-sensitive by default.

(Let ((x 1)) x) =>  Symbol's function definition is void: Let

(eq 'X 'x) => nil
From: Deepak Goel
Subject: Re: emacs let
Date: 
Message-ID: <ap3sne0yr8z.fsf@erie.umd.edu>
> Careful, Emacs lisp is case-sensitive by default.

That was my gnus :), configured to capitalize the first sentence of
each line i send..   wouldn't it be so cool if i could also teach it
to recognize code, and not capitalize that..


I gave this example:

(let ((x 1)) x)

x




<error..>

 to counter the claim of the OP that x is still bound outside the
	scope of let in emacs..


Have a good day,
Deepak				    <URL:http://www.glue.umd.edu/~deego>
--
   You know you've spent too much time on  emacs when you spill
   milk and the first thing you think is "C-_"
From: ···@itasoftware.com
Subject: Re: emacs let
Date: 
Message-ID: <elpj88y3.fsf@itasoftware.com>
Deepak Goel <·····@glue.umd.edu> writes:

> > Careful, Emacs lisp is case-sensitive by default.
> 
> That was my gnus :), configured to capitalize the first sentence of
> each line i send..   wouldn't it be so cool if i could also teach it
-----------------------^

It missed.

> to recognize code, and not capitalize that..
> 
> 
> I gave this example:
> 
> (let ((x 1)) x)
> 
> x
>
> <error..>
> 
>  to counter the claim of the OP that x is still bound outside the
> 	scope of let in emacs..

To be pedantic, x *is* bound outside the scope of the let, but not
outside the *extent* of the let.
From: Deepak Goel
Subject: Re: emacs let
Date: 
Message-ID: <ap3bsknf4nv.fsf@erie.umd.edu>
> > Each line i send..   Wouldn't it be so cool if i could also teach it
> -----------------------^
> 
> It missed.

Well, this time i didn't hit "y" to all the questions gnus asked me..
One of the questions was: "Capitalize all?" and since there was code
in the mail... :)

> To be pedantic, x *is* bound outside the scope of the let, but not
> outside the *extent* of the let.

Thanks.


Deepak				    <URL:http://www.glue.umd.edu/~deego>
--

 Any non-replies to mail are non-intentional... i have subscribed to
 one too many lists and personal mail can get filtered to some group
 by accident :(.    Gnus-gurus: suggestions?
From: Barry Margolin
Subject: Re: emacs let
Date: 
Message-ID: <X16m7.45$aL1.344@burlma1-snr2>
In article <············@itasoftware.com>,  <···@itasoftware.com> wrote:
>To be pedantic, x *is* bound outside the scope of the let, but not
>outside the *extent* of the let.

Well, if we're going to be pedantics, we might as well get it right.

The definition of "scope" is "the spatial or textual region of the program
in which references may occur".  If a variable is dynamically bound, the
scope is the entire program, except regions that shadow the binding with
their own lexical binding; CLTL uses the term "indefinite scope" for this.

You seem to be using "scope" to mean "the textual body of the let."  That
would be the scope of a variable in a *lexical* binding, but that's what
distinguishes lexical from dynamic bindings.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: ···@itasoftware.com
Subject: Re: emacs let
Date: 
Message-ID: <sndz6jkt.fsf@itasoftware.com>
Barry Margolin <······@genuity.net> writes:

> In article <············@itasoftware.com>,  <···@itasoftware.com> wrote:
> >To be pedantic, x *is* bound outside the scope of the let, but not
> >outside the *extent* of the let.
> 
> Well, if we're going to be pedantics, we might as well get it right.
> 
> The definition of "scope" is "the spatial or textual region of the program
> in which references may occur".  If a variable is dynamically bound, the
> scope is the entire program, except regions that shadow the binding with
> their own lexical binding; CLTL uses the term "indefinite scope" for this.
> 
> You seem to be using "scope" to mean "the textual body of the let."  That
> would be the scope of a variable in a *lexical* binding, but that's what
> distinguishes lexical from dynamic bindings.

You are even more correct (and pedantic) than I.  I was so focused on
`extent' that I overlooked the definition of `scope'.