Re: History of lexical scope in Lisp

Liste des GroupesRevenir à cl lisp 
Sujet : Re: History of lexical scope in Lisp
De : 433-929-6894 (at) *nospam* kylheku.com (Kaz Kylheku)
Groupes : comp.lang.lisp
Date : 16. Mar 2024, 18:54:05
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20240316093534.951@kylheku.com>
References : 1 2 3 4
User-Agent : slrn/pre1.0.4-9 (Linux)
On 2024-03-16, Jeff Barnett <jbb@notatt.com> wrote:
On 3/15/2024 4:26 PM, Lawrence D'Oliveiro wrote:
On Fri, 15 Mar 2024 16:05:37 -0600, Jeff Barnett wrote:
 
Once you have had the programming convenience of using dynamic scope,
you would miss it terribly in a lexical-only language, or worse, in
something like the old FORTRAN assembler-level scope. Another argument
that I have not seen debated but may be significant is that the CL Error
System -- the programming primitives and error class structures don't
make a lot of sense in lexical only. The error mechanisms like catch
have meanings that include phrases such as "while executing this. I'm
available to handle that".
 
Lexical binding has always been understood to apply to references to
definitions of identifiers. Exception handlers are dynamically-installed
(lexical-based exception handling doesn’t make any sense), nevertheless
the names of the defined exceptions being handled are still lexically-
bound.
 
This is how it works in every rationally-designed language.
>
First off, I believe that many if not most exception-related primitives
expand in terms of dynamic variables. And second, it would be amusing to
unwind to an environment that is lexically alive but execution dead-
think about restarting the contexts that were abandoned.

That might happen when you call a closure that was saved in such
an environment which was then dynamically abandoned.

When resuming a continuation captured in such an environment, though,
the dynamics have to appear intact.

  (defun grandkid ()
    (unwind-protect
      (yield-from parent 'in-grandkid)
      (put-line "returning from grandkid")))
 
  (defun kid ()
    (unwind-protect
      (progn
        (yield-from parent 'in-kid)
        (grandkid))
      (put-line "returning from kid")))

  (defun parent ()
    (unwind-protect
      (progn
        (yield-from parent 'in-parent)
        (kid))
      (put-line "returning from parent")))

  (let ((fn (obtain (parent))))
    (prinl 'a)
    (prinl (call fn))
    (prinl 'b)
    (prinl (call fn))
    (prinl 'c)
    (prinl (call fn))
    (prinl 'd)
    (prinl (call fn))
    (prinl 'e))

Run:

  $ txr cont.tl
  a
  in-parent
  b
  in-kid
  c
  in-grandkid
  d
  returning from grandkid
  returning from kid
  returning from parent
  nil
  e

When (call fn) resumes the delimited continuation, the stack linkage is all
there: the unwind protect exit points, and all else. Dynamic variable bindings
also, though that is not apparent in this example. If you resume a continuation
into somwhere where *stdout* is redirected to a string, it's redirected to a
string via dynamic binding, that redirection is correctly observed.

To make this work, I didn't even give a second thought to the horrendously
impractical "dynamic-wind", which is dead on arrival from a feasability
point of view.

How it works is that the yield-from invocations perform an "absconding"
dynamic control transfer. An absconding control transfer is like a regular
dynamic control transfer, except it performs no unwinding.

1> (block foo (unwind-protect (sys:abscond-from foo 42) (prinl 'unwind)))
42
2> (block foo (unwind-protect (return-from foo 42) (prinl 'notprinted)))
notprinted
42

Abscond is a sharp knife, so it's kept in the system package, though
it is a documented feature.

If we resume the came continuation, we can repeatedly invoke the
same unwinding:

  1> (block nil
       (unwind-protect
         (sys:capture-cont nil 'identity) ;; capture up to nil block
         (prinl 'unwind)))
  unwind
  #<intrinsic fun: 1 param>
  2> [*1 42]  ;; call continuation
  unwind
  42
  3> [*1 42]
  unwind
  42
  4> [*1 42]
  unwind
  42
  5> [*1 42]
  unwind
  42

(The yield stuff avoids this by updating the yield contexts to new
continuations which resume from the previously yielded point,
like a cooperative thread.)

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

Date Sujet#  Auteur
15 Mar 24 * History of lexical scope in Lisp23Paul Rubin
16 Mar 24 +* Re: History of lexical scope in Lisp14Jeff Barnett
16 Mar 24 i`* Re: History of lexical scope in Lisp13Lawrence D'Oliveiro
16 Mar 24 i +- Re: History of lexical scope in Lisp1Kaz Kylheku
16 Mar 24 i `* Re: History of lexical scope in Lisp11Jeff Barnett
16 Mar 24 i  +* Re: History of lexical scope in Lisp9Lawrence D'Oliveiro
17 Mar 24 i  i`* Re: History of lexical scope in Lisp8Jeff Barnett
17 Mar 24 i  i `* Re: History of lexical scope in Lisp7Lawrence D'Oliveiro
18 Mar 24 i  i  `* Re: History of lexical scope in Lisp6Jeff Barnett
18 Mar 24 i  i   +* Re: History of lexical scope in Lisp3Lawrence D'Oliveiro
19 Mar 24 i  i   i`* Re: History of lexical scope in Lisp2Jeff Barnett
19 Mar 24 i  i   i `- Re: History of lexical scope in Lisp1Lawrence D'Oliveiro
18 Mar 24 i  i   +- Re: History of lexical scope in Lisp1Lawrence D'Oliveiro
19 Mar 24 i  i   `- Re: History of lexical scope in Lisp1George Neuner
16 Mar 24 i  `- Re: History of lexical scope in Lisp1Kaz Kylheku
16 Mar 24 +* Re: History of lexical scope in Lisp4Robert Brown
16 Mar 24 i`* Re: History of lexical scope in Lisp3Lawrence D'Oliveiro
16 Mar 24 i `* Re: History of lexical scope in Lisp2Robert Brown
16 Mar 24 i  `- Re: History of lexical scope in Lisp1Lawrence D'Oliveiro
16 Mar 24 +- Re: History of lexical scope in Lisp1Kaz Kylheku
17 Mar 24 +* Re: History of lexical scope in Lisp2Didier Verna
17 Mar 24 i`- Re: History of lexical scope in Lisp1Lawrence D'Oliveiro
19 Mar 24 `- Re: History of lexical scope in Lisp1Johanne Fairchild

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal