From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,99ab4bb580fc34cd X-Google-Attributes: gid103376,public From: ok@goanna.cs.rmit.edu.au (Richard A. O'Keefe) Subject: Re: Q: access to subprogram Date: 1996/07/29 Message-ID: <4tha38$1p@goanna.cs.rmit.edu.au> X-Deja-AN: 170755517 references: <4rb9dp$qe6@news1.delphi.com> <4t9un9$imn@goanna.cs.rmit.edu.au> organization: Comp Sci, RMIT, Melbourne, Australia nntp-posting-user: ok newsgroups: comp.lang.ada Date: 1996-07-29T00:00:00+00:00 List-Id: bobduff@world.std.com (Robert A Duff) writes: >>Whenever you simulate any mechanism, >>...[all manner of evil happens] >True, but the logical conclusion is that all useful mechanisms that >anybody has ever thought of should be included in the language. One has >to make a trade-off between a useful gizmo and language complexity >(etc). I do not call that a logical conclusion. "All useful mechanisms which have ever been *commonly used* should be included" comes closer to being a reasonable generalisation of what I wrote. >Anyway, I think this argument is getting confused between "downward >closures" and "full closures". If I understand your example correctly, >it needs downward closures, but not full closures. Right. And that is all _I_ have ever been talking about in this thread. As it happens, I like full closures, principally because they fit very well with a "building blocks" approach to reuse, and because it greatly simplifies things like graphic programming in Clean: it's the *compiler's* job to worry about which things need to survive for a callback, not mine. But I am not advocating full closures (or continuations, or first class environments, or anything sexy) for Ada. All I am saying is that one specific feature -- downward funargs -- has proven its usefulness over many years in a lot of other languages, is demonstrably clumsy to simulate in Ada 83, can demonstrably be implemented efficiently by a compiler (5 seconds for the program in Scheme compiled by Stalin into C then into SPARC code by SPARCompiler C SC4.0, compared with 18 seconds for the program in Ada compiled by GNAT 3.04 GCC 2.7.2), was expected for Ada 95, but arrived in an unusable fashion because that feature was confounded with another feature, namely access-to-procedure. You can have nested procedures as parameters without procedure pointers (Pascal, Fortran, Algol 60). You have have procedure pointers without nested procedures as parameters (C). You can have both without restriction (Lisp, Scheme, ML, Smalltalk). The point is, you don't *have* to tangle them up, and the restrictions that are necessary for the one (procedure pointers) if you don't want to support full closures are NOT necessary for the other (procedures as parameters). Not only that, you *can* tangle them up in a different way from the Ada 95 way: you say that the lexical level of a procedure parameter is the lexical level of the procedure in whose header it appears, and forbid (copies) of that parameter outliving the callee. So it would have been possible to have both procedure pointers with a lexical level restriction (thus permitting an implementation in which library level pointers are fully compatible with C) *and* unrestricted passing of nested procedures as parameters. >I have argued >in favor of downward closures (because in my experience they have been >very useful, and they are very cheap to implement). But I remain >unconvinced about full closures (because they seem less commonly needed, >and they are substantially more expensive to implement -- although your >benchmark shows that in at least one case, the run-time cost is a myth). Ahem. My benchmark is solely concerned with DOWNward closures, not full closures. Just because I ran the benchmark in a language which supports full closures doesn't mean that the benchmark itself used that power. >And the only serious example anybody posted was Ackermann's function, >which is useful in explaining how full closures work, but doesn't >exactly make me want to use them every day. Well, the classic application of full closures in Scheme is OOP. Scheme has far too many OOP dialects, because it is extremely easy for everyone to implement their own OOP system using closures. The classic *idiom* using closures is simulating modules: (define export1) ; top level placeholder declarations (define export2) (let ( <> ) (set! export1 (lambda <> <>)) (set! export2 (lambda <> <>))) The exported functions have access to the local declarations. My argument about simulation extends to this as well: it is better to have a module construct so that the compiler knows what you are up to and can check that you got it right. -- Fifty years of programming language research, and we end up with C++ ??? Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci.