Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.lisp > #59450 > unrolled thread
| Started by | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| First post | 2024-03-15 11:55 -0700 |
| Last post | 2024-03-19 06:07 -0300 |
| Articles | 20 on this page of 24 — 9 participants |
Back to article view | Back to comp.lang.lisp
History of lexical scope in Lisp Paul Rubin <no.email@nospam.invalid> - 2024-03-15 11:55 -0700
Re: History of lexical scope in Lisp Jeff Barnett <jbb@notatt.com> - 2024-03-15 16:05 -0600
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-15 22:26 +0000
Re: History of lexical scope in Lisp Kaz Kylheku <433-929-6894@kylheku.com> - 2024-03-15 23:04 +0000
Re: History of lexical scope in Lisp Jeff Barnett <jbb@notatt.com> - 2024-03-16 00:46 -0600
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-16 07:27 +0000
Re: History of lexical scope in Lisp Jeff Barnett <jbb@notatt.com> - 2024-03-16 23:13 -0600
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-17 05:37 +0000
Re: History of lexical scope in Lisp Jeff Barnett <jbb@notatt.com> - 2024-03-17 16:42 -0600
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-17 23:05 +0000
Re: History of lexical scope in Lisp Jeff Barnett <jbb@notatt.com> - 2024-03-18 23:02 -0600
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-19 05:44 +0000
Re: History of lexical scope in Lisp albert@spenarnc.xs4all.nl - 2024-03-18 14:47 +0100
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-18 19:51 +0000
Re: History of lexical scope in Lisp George Neuner <gneuner2@comcast.net> - 2024-03-18 20:33 -0400
Re: History of lexical scope in Lisp Kaz Kylheku <433-929-6894@kylheku.com> - 2024-03-16 16:54 +0000
Re: History of lexical scope in Lisp Robert Brown <robert.brown@gmail.com> - 2024-03-15 20:23 -0400
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-16 01:03 +0000
Re: History of lexical scope in Lisp Robert Brown <robert.brown@gmail.com> - 2024-03-16 11:32 -0400
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-16 21:59 +0000
Re: History of lexical scope in Lisp Kaz Kylheku <433-929-6894@kylheku.com> - 2024-03-16 02:37 +0000
Re: History of lexical scope in Lisp Didier Verna <didier@didierverna.net> - 2024-03-17 10:41 +0100
Re: History of lexical scope in Lisp Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-03-17 21:12 +0000
Re: History of lexical scope in Lisp Johanne Fairchild <jfairchild@tudado.org> - 2024-03-19 06:07 -0300
Page 1 of 2 [1] 2 Next page →
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2024-03-15 11:55 -0700 |
| Subject | History of lexical scope in Lisp |
| Message-ID | <874jd7z5nf.fsf@nightsong.com> |
Does anyone know when lexical scope started appearing in Lisp? Not counting Scheme, did it exist in predecessors of Common Lisp? Was it used much? Is it really true that Common Lisp had both lexical and dynamic scope in order to support older code that was written relying on dynamic scope and was too hard to convert? Thanks. This topic came up in the Forth group.
[toc] | [next] | [standalone]
| From | Jeff Barnett <jbb@notatt.com> |
|---|---|
| Date | 2024-03-15 16:05 -0600 |
| Message-ID | <ut2gnj$2g8k5$1@dont-email.me> |
| In reply to | #59450 |
On 3/15/2024 12:55 PM, Paul Rubin wrote: > Does anyone know when lexical scope started appearing in Lisp? Not > counting Scheme, did it exist in predecessors of Common Lisp? Was it > used much? Is it really true that Common Lisp had both lexical and > dynamic scope in order to support older code that was written relying on > dynamic scope and was too hard to convert? > > Thanks. This topic came up in the Forth group. I'll comment on only a part of your questions, namely whether CL had dynamic scope only for compatibility? The view that I and many others had was that compatibility made it a must AND: 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". The availability of such fine grained control structures makes many typical Lisp non-hierarchical reasoning* programs possible. I believe that the early and middle AI communities were drawn to Lisp-like development tools because of these possibilities. * By non-hierarchical reasoning, I'm thinking of Simon's "almost decomposable systems" ideas. -- Jeff Barnett
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-15 22:26 +0000 |
| Message-ID | <ut2hvh$2gft8$1@dont-email.me> |
| In reply to | #59451 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <433-929-6894@kylheku.com> |
|---|---|
| Date | 2024-03-15 23:04 +0000 |
| Message-ID | <20240315155740.155@kylheku.com> |
| In reply to | #59452 |
On 2024-03-15, Lawrence D'Oliveiro <ldo@nz.invalid> 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. Names of exceptions (conditions) are not lexically bound in Common Lisp. They are pervasive, similarly to class names. Lexically scoped exception handling does make sense, during those sections of the handling when a lexical scope isn't being abandoned. If the termination point of an exception is in lexical scope of the origin, then the case can be made for handling the entire episode lexically, including the unwinding. -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal Mastodon: @Kazinator@mstdn.ca
[toc] | [prev] | [next] | [standalone]
| From | Jeff Barnett <jbb@notatt.com> |
|---|---|
| Date | 2024-03-16 00:46 -0600 |
| Message-ID | <ut3f7t$2p3sa$1@dont-email.me> |
| In reply to | #59452 |
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. -- Jeff Barnett
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-16 07:27 +0000 |
| Message-ID | <ut3hlt$2pi20$1@dont-email.me> |
| In reply to | #59457 |
On Sat, 16 Mar 2024 00:46:21 -0600, Jeff Barnett wrote:
> First off, I believe that many if not most exception-related primitives
> expand in terms of dynamic variables.
Consider the following Python example:
class MyException1(Exception) :
pass
#end MyException1
class MyException2(Exception) :
pass
#end MyException2
def func1() :
raise MyException1
#end func1
def func2() :
raise MyException2
#end func2
def func3() :
class MyException1(Exception) :
pass
#end MyException1
try :
func1()
except MyException1 :
# will never get here
print("caught MyException1 in func3")
#end try
#end func3
def func4() :
try :
func2()
except MyException2 :
print("caught MyException2 in func4")
#end try
#end func4
for f in (func1, func2, func3, func4) :
try :
print("* call %s" % f.__name__)
f()
except MyException1 :
print("caught MyException1 at top level")
except MyException2 :
print("caught MyException2 at top level")
#end try
#end for
Here is the output it produces:
* call func1
caught MyException1 at top level
* call func2
caught MyException2 at top level
* call func3
caught MyException1 at top level
* call func4
caught MyException2 in func4
func4 shows how the search for a handler is based on dynamic execution
nesting. func3 shows how exception matching is based on lexical
scoping.
[toc] | [prev] | [next] | [standalone]
| From | Jeff Barnett <jbb@notatt.com> |
|---|---|
| Date | 2024-03-16 23:13 -0600 |
| Message-ID | <ut5u5i$3c0e6$1@dont-email.me> |
| In reply to | #59458 |
On 3/16/2024 1:27 AM, Lawrence D'Oliveiro wrote:
> On Sat, 16 Mar 2024 00:46:21 -0600, Jeff Barnett wrote:
>
>> First off, I believe that many if not most exception-related primitives
>> expand in terms of dynamic variables.
>
> Consider the following Python example:
>
> class MyException1(Exception) :
> pass
> #end MyException1
>
> class MyException2(Exception) :
> pass
> #end MyException2
>
> def func1() :
> raise MyException1
> #end func1
>
> def func2() :
> raise MyException2
> #end func2
>
> def func3() :
> class MyException1(Exception) :
> pass
> #end MyException1
>
> try :
> func1()
> except MyException1 :
> # will never get here
> print("caught MyException1 in func3")
> #end try
> #end func3
>
> def func4() :
> try :
> func2()
> except MyException2 :
> print("caught MyException2 in func4")
> #end try
> #end func4
>
> for f in (func1, func2, func3, func4) :
> try :
> print("* call %s" % f.__name__)
> f()
> except MyException1 :
> print("caught MyException1 at top level")
> except MyException2 :
> print("caught MyException2 at top level")
> #end try
> #end for
>
> Here is the output it produces:
>
> * call func1
> caught MyException1 at top level
> * call func2
> caught MyException2 at top level
> * call func3
> caught MyException1 at top level
> * call func4
> caught MyException2 in func4
>
> func4 shows how the search for a handler is based on dynamic execution
> nesting. func3 shows how exception matching is based on lexical
> scoping.
Unfortunately, I don't speak Python. However if your point is that you
can build "simulations" of one sort of scoping out of primitives for
another sort, I agree.
In fact Doug Pintar and I invented and used a language called CRISP
(https://www.softwarepreservation.org/projects/LISP/crisp_ibm370_sdc) in
the 1070s. It was used to implement some interesting speech
understanding systems as part of the DARPA SUR Program. CRISP Allowed
local and dynamic bindings and stack segments including bindings,
catches, and return points where represented. There where primitives
that allowed these stack segments to be elements of three types of
trees: binding trees where dynamic bindings not located in one segment
where sought in the parent segment; resume trees where segment
executions did a return that was not handled in the current segment were
reflected to the parent segment; and handler trees where a throw not
handled by the executing segment was continued into the parent segment.
The "highest" node in all trees was the global context. The parent-child
relation in all trees could be rearranged under program control. Out of
the related primitives, e.g., eval-in(exp, segment) you could construct
pretty much whatever binding, control. and error handling structure that
you needed. The reason for this baroque approach is that when we started
constructing speech systems we had absolutely no idea what program
organization structures would be convenient.
The above was inspired by some papers using the rubric "spaghetti
stacks". Don't remember the authors but Danny Bobrow might have been
implicated.
--
Jeff Barnett
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-17 05:37 +0000 |
| Message-ID | <ut5vjg$3c7pv$2@dont-email.me> |
| In reply to | #59463 |
On Sat, 16 Mar 2024 23:13:20 -0600, Jeff Barnett wrote: > However if your point is that you can build "simulations" of one sort of > scoping out of primitives for another sort ... No, my point was that there seems to be no need for dynamic scoping, if the only excuse anyone can come up for needing it comes out of exception handling.
[toc] | [prev] | [next] | [standalone]
| From | Jeff Barnett <jbb@notatt.com> |
|---|---|
| Date | 2024-03-17 16:42 -0600 |
| Message-ID | <ut7rkt$3p750$1@dont-email.me> |
| In reply to | #59464 |
On 3/16/2024 11:37 PM, Lawrence D'Oliveiro wrote: > On Sat, 16 Mar 2024 23:13:20 -0600, Jeff Barnett wrote: > >> However if your point is that you can build "simulations" of one sort of >> scoping out of primitives for another sort ... > > No, my point was that there seems to be no need for dynamic scoping, if > the only excuse anyone can come up for needing it comes out of exception > handling. That wasn't the only thing mentioned. In fact it was said to be quite useful and desired without enumeration of reasons. You of course chopped many original messages above to remove some of those "short glowing reviews" then got on your hobby horse and started to ride. Just think of the following when specifying a variable's intent: is it supposed to influence an evaluation or is it supposed to influence an evaluation when it's in a particular lexical scope? Does that help you any? The example of error handling is that it's generally supposed to control an evaluation. If error handling was lexically based then you would need to decide what to do when evaluate(x) occurs and the handling of certain conditions are specified in a scope not available when x was defined. There are choices and lots of them. When dynamic and lexical flow trees are different, you must decide by language rules or provide primitives to users that allows them to sort out intent. If you don't have any "special" variables around, you'll find that rather difficult. Lexical-only is nice and neat for many applications and philosophies of programming. But not all by a long shot. If that approach satisfies you, I'd suggest ALGOL or even SIMULA. Alan Perlis even saw uses for dynamic visibility (private communications) and discussed the thought that OWN variables did not satisfy those uses. There was an ambiguity in the second ALGOL spec on the requirements for OWN variables: if the spec was read one way, a particular function computed a Legendre polynomial; read the other way, it computed a Bessel function! (It's been a long time and I don't remember the exact pair of function families that were confounded.) In any event, the issue had to do for the rules about when an OWN needed to be bound and it was possible to have multiple bindings simultaneously! I believe this latter fact was tied up with trying to allow OWNS to act more like SPECIAL. -- Jeff Barnett
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-17 23:05 +0000 |
| Message-ID | <ut7svi$3pbnh$2@dont-email.me> |
| In reply to | #59467 |
On Sun, 17 Mar 2024 16:42:34 -0600, Jeff Barnett wrote: > Just think of the following when specifying a variable's intent: is it > supposed to influence an evaluation or is it supposed to influence an > evaluation when it's in a particular lexical scope? Does that help you > any? Seems you phrased that wrong: it should be “is it supposed to influence an evaluation or is it supposed to influence an evaluation when it’s in a particular *dynamic* scope”? Because a variable in a lexical scope is always in that lexical scope, no “when” about it. > The example of error handling is that it's generally supposed to control > an evaluation. If error handling was lexically based ... I didn’t say error handling was lexically based, I said the matching of exceptions was lexically based. I thought my example made that distinction clear.
[toc] | [prev] | [next] | [standalone]
| From | Jeff Barnett <jbb@notatt.com> |
|---|---|
| Date | 2024-03-18 23:02 -0600 |
| Message-ID | <utb691$leks$1@dont-email.me> |
| In reply to | #59468 |
On 3/17/2024 5:05 PM, Lawrence D'Oliveiro wrote: > On Sun, 17 Mar 2024 16:42:34 -0600, Jeff Barnett wrote: > >> Just think of the following when specifying a variable's intent: is it >> supposed to influence an evaluation or is it supposed to influence an >> evaluation when it's in a particular lexical scope? Does that help you >> any? > > Seems you phrased that wrong: it should be “is it supposed to influence an > evaluation or is it supposed to influence an evaluation when it’s in a > particular *dynamic* scope”? Because a variable in a lexical scope is > always in that lexical scope, no “when” about it. Given the sort of languages we are talking about (e.g., not CRISP described above) you really can't escape from one dynamic scope to another. You need coroutines that have no start/restart commitments to one another. >> The example of error handling is that it's generally supposed to control >> an evaluation. If error handling was lexically based ... > > I didn’t say error handling was lexically based, I said the matching of > exceptions was lexically based. I thought my example made that distinction > clear. Maybe it did but not to me. -- Jeff Barnett
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-19 05:44 +0000 |
| Message-ID | <utb8on$lttb$1@dont-email.me> |
| In reply to | #59472 |
On Mon, 18 Mar 2024 23:02:23 -0600, Jeff Barnett wrote:
> ... you really can't escape from one dynamic scope to
> another.
Au contraire, with dynamic scoping, such “escaping” happens all the time.
Here’s an example from a language, namely Perl, which does allow for
dynamic scoping (in fact, early on it had no lexical scoping):
$a = 1;
sub f1()
{
$a = $a + 1;
} # f1
sub f2()
{
local $a = 3;
print "inner ", $a, "\n";
f1();
print "inner ", $a, "\n";
} # f2
f1();
print "outer ", $a, "\n";
f2();
print "outer ", $a, "\n";
f1();
print "outer ", $a, "\n";
The output is
outer 2
inner 3
inner 4
outer 2
outer 3
>> I didn’t say error handling was lexically based, I said the matching of
>> exceptions was lexically based. I thought my example made that
>> distinction clear.
>
> Maybe it did but not to me.
Look back again, and see how the outer exception is not the same as the
one with the same name local to the function, yet the catch clauses search
for the exceptions according to dynamic execution nesting.
Want me to go over it step-by-step?
[toc] | [prev] | [next] | [standalone]
| From | albert@spenarnc.xs4all.nl |
|---|---|
| Date | 2024-03-18 14:47 +0100 |
| Message-ID | <nnd$79e8f550$72629b38@7ae82f9f1ca9b0e9> |
| In reply to | #59467 |
In article <ut7rkt$3p750$1@dont-email.me>, Jeff Barnett <jbb@notatt.com> wrote: >second ALGOL spec on the requirements for OWN variables: if the spec was You can't refer to ALGOL like this. It is either ALGOL60 or ALGOL68. These are totally different languages. ALGOL60 is an early experiment. ALGOL68 is practically Google's go. >-- >Jeff Barnett > -- Don't praise the day before the evening. One swallow doesn't make spring. You must not say "hey" before you have crossed the bridge. Don't sell the hide of the bear until you shot it. Better one bird in the hand than ten in the air. First gain is a cat purring. - the Wise from Antrim -
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-18 19:51 +0000 |
| Message-ID | <uta5vv$bdg5$3@dont-email.me> |
| In reply to | #59469 |
On Mon, 18 Mar 2024 14:47:29 +0100, albert wrote: > ALGOL60 is an early experiment. Actually, the “early experiment” was IAL, a.k.a. ALGOL58. And then there was “ALGOL-W”, a.k.a. “Wirth-Hoare ALGOL”, which was the precursor to Pascal.
[toc] | [prev] | [next] | [standalone]
| From | George Neuner <gneuner2@comcast.net> |
|---|---|
| Date | 2024-03-18 20:33 -0400 |
| Message-ID | <bgehvi9elnkgo6qjchi1dvlks1du5tvo0s@4ax.com> |
| In reply to | #59469 |
On Mon, 18 Mar 2024 14:47:29 +0100, albert@spenarnc.xs4all.nl wrote: >In article <ut7rkt$3p750$1@dont-email.me>, >Jeff Barnett <jbb@notatt.com> wrote: >>second ALGOL spec on the requirements for OWN variables: if the spec was > >You can't refer to ALGOL like this. It is either ALGOL60 or ALGOL68. >These are totally different languages. >ALGOL60 is an early experiment. ALGOL68 is practically Google's go. FWIW: ALGOL68 was described by two different reports using completely different grammar notation. [1] Report on the Algorithmic Language ALGOL 68 [2] Revised Report on the Algorithmic Language ALGOL 68 The original report used a "Van Wijngaarden" (vW) grammar. vW grammars are 2-level, consisting of a conventional attribute grammar, augmented by a "meta" grammar which describes the possible values of attributes in the 1st grammar. In theory, a vW grammar can do wonderful things such as turn type errors into syntax errors. Unfortunately, vW grammars are Turing Complete - programming languages in themselves. The grammar in the ALGOL 68 report widely was considered to be too difficult for many compiler implementors to understand. Thus the report was rewritten using an adhoc notation called "NEST" [which AFAICT was never used again]. NEST also was 2-level and able to describe attribute values, but more verbose than vW, and deliberately made not Turing Complete. However, the grammars in the two reports are so different that they are difficult to compare, and there was/is some debate as to whether they truly describe the same language. In any event, almost all AlGOL68 compilers were said to have been developed using the revised report. [1] https://pdfroom.com/books/report-on-the-algorithmic-language-algol-68/Jr2ELK1agyv [2] https://www.softwarepreservation.org/projects/ALGOL/report/Algol68_revised_report-AB-600dpi.pdf
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <433-929-6894@kylheku.com> |
|---|---|
| Date | 2024-03-16 16:54 +0000 |
| Message-ID | <20240316093534.951@kylheku.com> |
| In reply to | #59457 |
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
[toc] | [prev] | [next] | [standalone]
| From | Robert Brown <robert.brown@gmail.com> |
|---|---|
| Date | 2024-03-15 20:23 -0400 |
| Message-ID | <871q8bja7c.fsf@gmail.com> |
| In reply to | #59450 |
Paul Rubin <no.email@nospam.invalid> writes: > Is it really true that Common Lisp had both lexical and dynamic scope > in order to support older code that was written relying on dynamic > scope and was too hard to convert? No. I'd say Common Lisp has both lexical and dynamic scope because both are very useful. For instance, the Guice dependency injection framework for Java implements @RequestScoped settings, which are dynamically scoped and thread local. Guice wouldn't need that feature if Java natively supported dynamically-scoped variables.
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-16 01:03 +0000 |
| Message-ID | <ut2r5n$2i048$4@dont-email.me> |
| In reply to | #59454 |
On Fri, 15 Mar 2024 20:23:51 -0400, Robert Brown wrote:
> For instance, the Guice dependency injection framework
> for Java implements @RequestScoped settings, which are dynamically
> scoped and thread local.
Can’t find any mention of “dynamic” scoping in the docs
<https://github.com/google/guice/wiki/Scopes>. “@RequestScoped” just
seems to mean what it says: the scope is per-request.
> Guice wouldn't need that feature if Java
> natively supported dynamically-scoped variables.
It seems to me the effect can be achieved more simply by allowing
access to instance methods as first-class objects, as you can do in
Python, e.g.
request_inst = Request(...)
# class instantiation
request_meth = request_inst.meth
# method access
But as usual, Java insists on doing things in a complicated way...
[toc] | [prev] | [next] | [standalone]
| From | Robert Brown <robert.brown@gmail.com> |
|---|---|
| Date | 2024-03-16 11:32 -0400 |
| Message-ID | <87il1mgpk1.fsf@gmail.com> |
| In reply to | #59455 |
Lawrence D'Oliveiro <ldo@nz.invalid> writes: > On Fri, 15 Mar 2024 20:23:51 -0400, Robert Brown wrote: > >> For instance, the Guice dependency injection framework >> for Java implements @RequestScoped settings, which are dynamically >> scoped and thread local. > > Can’t find any mention of “dynamic” scoping in the docs > <https://github.com/google/guice/wiki/Scopes>. “@RequestScoped” just > seems to mean what it says: the scope is per-request. The use of thread local state to store request scoped Guice bindings is discussed in this thread: https://groups.google.com/g/google-guice/c/gDonVGO1wjY/m/_SSi4CcQAJYJ
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D'Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2024-03-16 21:59 +0000 |
| Message-ID | <ut54ne$33m2r$5@dont-email.me> |
| In reply to | #59460 |
On Sat, 16 Mar 2024 11:32:46 -0400, Robert Brown wrote: > Lawrence D'Oliveiro <ldo@nz.invalid> writes: > >> On Fri, 15 Mar 2024 20:23:51 -0400, Robert Brown wrote: >> >>> For instance, the Guice dependency injection framework for Java >>> implements @RequestScoped settings, which are dynamically scoped and >>> thread local. >> >> Can’t find any mention of “dynamic” scoping in the docs >> <https://github.com/google/guice/wiki/Scopes>. “@RequestScoped” just >> seems to mean what it says: the scope is per-request. > > The use of thread local state to store request scoped Guice bindings is > discussed in this thread: > > https://groups.google.com/g/google-guice/c/gDonVGO1wjY/m/_SSi4CcQAJYJ You mean the commenter who says “I'm not saying this is often (or even ever) a good thing to do; I'm just illustrating the technique”?
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.lisp
csiph-web