From: Jeff M.
Subject: Lexical vs. Dynamic bindings
Date: 
Message-ID: <9db6f632-c87a-48e3-b268-3c678a78c966@x38g2000yqj.googlegroups.com>
Recently I decided to go back through various old PDFs I have
discussing various Lisp implementations. In re-reading Pico Lisp's "A
Radial Approach to Application Development" (http://software-lab.de/
radical.pdf) I came to section 2.3, "Myth 3: Dynamic Binding is Bad".

If I understand what I read correctly, I'm trying to comprehend
whether or not Pico Lisp can support full closures, since all bindings
are dynamic (except for a couple cases in which the document discusses
"transient" symbols). Is it possible to use only dynamic bindings and
still support closures? If so, how? Can someone provide me with an
example of how this might be implemented?

Just to be clear, I use the term "closure" to describe a function that
executes within an environment. So...

(let ((n 5))
  #'(lambda (x) (+ x n)))

The above is a closure, where-as:

(map #'(lambda (x) (1+ x)) '(1 2 3))

Is just an anonymous function (actually, it's likely still a closure
given that it is compiled inside a lexical environment, but for the
sake of the example...).

Finally, given the short description provided in section 2.3 of the
document, can someone describe to me what exactly a "transient symbol"
is supposed to be?

Thanks!

Jeff M.

From: ·······@gmail.com
Subject: Re: Lexical vs. Dynamic bindings
Date: 
Message-ID: <d5ada753-14cb-44d7-8896-065fcdeb03f9@t11g2000yqg.googlegroups.com>
On Feb 20, 3:02 pm, "Jeff M." <·······@gmail.com> wrote:
> Is it possible to use only dynamic bindings and
> still support closures?

Yes.

http://portal.acm.org/citation.cfm?id=362379

The Evolution of Lisp:

> One of the most innovative of the language extensions introduced by
> Interlisp was the spaghetti stack [Bobrow, 1973]. The problem of
> retention (by closures) of the dynamic function-definition environment
> in the presence of special variables was never completely solved until
> spaghetti stacks were invented.

> The idea behind spaghetti stacks is to generalize the structure of
> stacks to be more like a tree, with various branches of the tree
> subject to retention whenever a pointer to that branch is retained.
> That is, parts of the stack are subject to the same garbage collection
> policies as are other Lisp objects. Unlike closures, the retained
> environment captures both the control environment and the binding
> environment.

Link here:
http://www.softwarepreservation.org/projects/LISP/index.html#Papers_about_LISP_history_
From: Alexander Burger
Subject: Re: Lexical vs. Dynamic bindings
Date: 
Message-ID: <gnpgpb$vvj$1@online.de>
Jeff M. <·······@gmail.com> wrote:
> "transient" symbols). Is it possible to use only dynamic bindings and
> still support closures? If so, how? Can someone provide me with an
> example of how this might be implemented?

Yes, but in PicoLisp you have to do it explicitly.


> Just to be clear, I use the term "closure" to describe a function that
> executes within an environment. So...

> (let ((n 5))
>   #'(lambda (x) (+ x n)))

'job' is often used to maintain dynamic environments, though it is
seldom called directly. We could use 'curry'

   : (let N 5
      (def 'foo
         (curry (N)
            (X) (+ X N) ) ) )

and get this function

   : (pp 'foo)                
   (de foo (X)
      (job '((N . 5)) (+ X N)) )

You see that 'job' holds its environment in the association list.
It binds the symbols (here only 'N') dynamically, executes the body
(here (+ X N)), and the unbinds the symbols again.

   : (foo 7)  
   -> 12


Holding the environment explicitly in a Lisp data structure has
quite some advantages. It is useful during debugging, allows
to modify the environment or build it from external sources,
or pass it to other processes via pipes and sockets.


BTW, 'job' is a bit overkill here, as 'N' is constant. Another
possibility is:

   : (let @N 5
      (def 'bar
         (curry (@N)
            (X) (+ X @N) ) ) )

   : (pp 'bar)                    
   (de bar (X)
      (+ X 5) )

So this is simpler and more efficient.

   : (bar 7)  
   -> 12


But if the value of 'N' is not constant

   : (let N 5
      (def 'mumble
         (curry (N)
            (X) (+ X (inc 'N)) ) ) )

   : (pp 'mumble)                       
   (de mumble (X)
      (job '((N . 5)) (+ X (inc 'N))) )

   : (mumble 1)  
   -> 7

   : (mumble 2)
   -> 9

   : (pp 'mumble)
   (de mumble (X)
      (job '((N . 7)) (+ X (inc 'N))) )



> Finally, given the short description provided in section 2.3 of the
> document, can someone describe to me what exactly a "transient symbol"
> is supposed to be?

A "transient" symbol is visible only within a single 'load' environment
(typically, but not always, a source file). This is quite analogous
to a "static" identifier in C. See also

   http://www.software-lab.de/ref.html#transient
   http://www.software-lab.de/ref.html#transient-io

Thus, "transient" symbols have a lexical scope.

_Binding_ of symbol values is always dynamically in PicoLisp,
but the _scope_ of symbols is

   - global for normal, "internal" symbols
   - per 'load' environment for "transient" symbols, and
   - per database for "external" symbols

Cheers,
- Alex
-- 
   Software Lab. Alexander Burger
   Bahnhofstr. 24a, D-86462 Langweid
   ···@software-lab.de, www.software-lab.de, +49 8230 5060