aarons@cvaxa.sussex.ac.uk (Aaron Sloman) (07/07/88)
>From: manis@faculty.cs.ubc.ca (Vincent Manis) >Message-ID: <3257@ubc-cs.UUCP> >Date: 21 Jun 88 19:59:42 GMT > ....... >I think it's a mistake to define an internal definition to change the >*global* value of the function cell: this is almost always not what >one would expect, given lexical binding. Either don't provide it at >all (as CL doesn't) or give it the same semantics as in Scheme. I absolutely agree, except that the point is not restricted to lexical binding, and "almost" should have been omitted. Allowing properly nested function definitions is very useful and has been used by the Pop community for some time. Pop-11 allows properly nested definitions for both lexically and dynamically scoped names of functions. E.g. the main interrupt handler (whose name is dynamically scoped) is locally re-definable thus: define foo .....; define interrupt; <interrupt behaviour desired whilst foo is running> enddefine; <code for foo> enddefine; Because it is a truly local definition, any normal or abnormal exit from foo will re-set the global value of interrupt. Some procedures running in the environment of foo may also locally redefine interrupt to do something different again. Similarly one can locally redefine the current error handler, the current output character consumer used by all the standard printing funcions, etc. etc. This facility has been generally available in all Pop systems since around 1970 I think. In Poplog Pop-11, lexically scoped local definitions allow safe use of functions that are called from other locally defined functions given as arguments to externally defined functions. e.g. in Poplog Pop-11 define foo ..... define lconstant baz ...; ;;; lconstant makes baz lexical and <code for baz> ;;; constant (lvars makes it variable) enddefine; define grum ...; <code for grum INCLUDING a call of baz> enddefine; other_function(grum) ;;; other_function will run grum enddefine; Lexical scoping of baz ensures that when other_function runs grum, grum will call the baz that was defined in foo, ignoring, for example, a function baz that is local to other_function. In this context it doesn't matter whether grum is lexically or dynamically scoped, since only the value, i.e. the function itself, is passed to other_function, not the name. Similarly lexical scoping ensures that if foo return grum as a result, or stores it in a data structure for future use in an unknown calling environment, there is never any risk that when it is run it will invoke any other version of baz than the one defined within foo. Aaron Sloman, School of Cognitive and Computing Sciences, Univ of Sussex, Brighton, BN1 9QN, England ARPANET : aarons%uk.ac.sussex.cvaxa@nss.cs.ucl.ac.uk JANET aarons@cvaxa.sussex.ac.uk BITNET: aarons%uk.ac.sussex.cvaxa@uk.ac