Path: utzoo!mnetor!tmsoft!torsqnt!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!mcsun!ukc!edcastle!aiai!jeff From: jeff@aiai.ed.ac.uk (Jeff Dalton) Newsgroups: comp.lang.lisp Subject: Re: In defense of call/cc (and a plug for T) Message-ID: <4138@skye.ed.ac.uk> Date: 15 Feb 91 14:02:33 GMT References: <1991Feb12.233157.20820@elroy.jpl.nasa.gov> <1991Feb13.055938.22853@Think.COM> Reply-To: jeff@aiai.UUCP (Jeff Dalton) Organization: AIAI, University of Edinburgh, Scotland Lines: 109 In article pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: >barmar> I wasn't in the original Common Lisp design group. However, it >barmar> seems obvious that they explicitly decided against allowing >barmar> upward closures to capture control state. Had they not made >barmar> this decision, call/cc could be implemented in terms of closures >barmar> or vice versa. > >This would a be a misdesign. The point about call/cc is that allows you >to actualize an arbitrary control graph, instead of a control tree >linearized onto a stack (usual case) or on multiple stacks (coroutines >as stack groups). > >Closures are completely orthogonal to continuations; closures allow you >to actualize an arbitrary context graph, instead of a context tree >linearized onto a stack or multiple stacks. Incidentally, fully general >closures also obviate the need for packages. I agree that closures and continuations should be regarded as distinct. The spaghetti stack view of things, where the access link and the control link seem very similar things, may be one reason for the "closures subsume continuations" view. However, fully general closures do not obviate the need for packages, because (1) packages are also used for data structuring (ie, controlling the potentially huge number of symbols), (2) it's much easier to make macros work reasonably with packages than with modules that are based on closures / environments. And let's not pretend that there are no costs to call/cc, only benefits. That is simply false. I think the right question to ask is whether a Lisp that has lexical closures and coroutines needs to go further and add call/cc (and take out coroutines or reimplement them with call/cc). My view is that we have by then reached the point of substantially diminishing returns. Moreover, the coroutines that one can implement oneself with call/cc tend to be less usable than those that are provided with the language. >As to being necessary, both are simply indispensable; you need both >arbitrary context and control graphs in all algorithms that deal with >non trivial graph walking, or equivalents. > >Many programmers do not realize this, they keep reimplementing closures >and continuations "manually", simulating closures usually with bunches >of global variables and continuations with state machines or "markers". There are much better "simulations", sometimes of both together. For example, agendas are often used to implement control. And a typical agenda would have entries that each contained a function and some arguments to apply it to (a simulated closure, if you will). Other better simulations for non-trivial graph-walking are streams (ie, lazy lists) and explicit continuation functions (eg, the caller passes a function to be called on success). >barmar> What if we were to add a coroutine facility, rather than a >barmar> primitive for building coroutines? ... prefer to define >barmar> user-oriented facilities, rather than implementor-oriented >barmar> primitives. > >In other words you are saying that CL is by design a "programming" >language, like PL/1 or PERL, not an algorithmic language like Scheme or >C or the Bourne shell. This is pretty amusing. CL is like PL/1 because it aims to be useful for programming. I agree with Barmar about coroutines (though not quite about the user/implementor distinction). And this is in part because I think different things are appropriate for different languages, and that more than one of these combinations can be good. Some people seem to feel that there is essentially only one good way to do things and that any language that does something else must therefore be worse. These people are invited to define the One True Language and then set about convincing everyone to use it. The slightly more generous view in which there is a class of good languages (the "algorithmic languages", say) and a class of bad ones (those that can be claimed to be like PL/1) has similar problems. In particular it still fails to recognize that there can be more than one good way of doing things and so ends up regarding everyone who does things the "bad" way as misinformed, misguided, or worse. Let several language design philosophy flowers bloom, at least. >This philosphy is one of the reasons why CL is perceived as a jumble >sale of features, a giant and monolithic entity. A giant and monolithic entity and a jumble sale of features seem rather different to me, but I would agree that such perceptions often go together. I think that one of the most important reasons why CL is sometimes perceived as a jumble sale is that it is mistakenly supposed that CL was designed by taking every feature from every Lisp and putting it in Common Lisp. But that isn't true. CL is a cleaner and simpler design in many ways than, say, InterLisp; and many of the features that appear most in complaints (loop, format, dotimes, multiple values) were already used, in one form or another, in MacLisp. Indeed, a fairly common view (at least in the UK) is that the scoping rules for CL (where lexical/static and special/dynamic are both supported) are as they are because of some union of features approach. However, what they actually are is a cleanup and generalization of the rules in MacLisp. -- jd