Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!mcsun!ukc!dcl-cs!aber-cs!athene!pcg From: pcg@cs.aber.ac.uk (Piercarlo Grandi) Newsgroups: comp.object Subject: Re: The Emperor Strikes Back Message-ID: Date: 27 Feb 91 18:30:32 GMT References: <3351@sequent.cs.qmw.ac.uk> <1991Feb23.075248.10519@Think.COM> Sender: aro@aber-cs.UUCP Distribution: comp.object Organization: Coleg Prifysgol Cymru Lines: 124 Nntp-Posting-Host: odin In-reply-to: barmar@think.com's message of 23 Feb 91 07:52:48 GMT On 23 Feb 91 07:52:48 GMT, barmar@think.com (Barry Margolin) said: barmar> I believe the lexical scoping referred to is the implementation barmar> of instances as procedures that remember their instance barmar> variables in lexical variables, e.g.: [ ... ] I will, as my habit is, expand a bit on this. You will already know all this, but somebody else seems in need of a bit of refreshing :-). What you describe is actually how objects are implemented in all OO non actor languages. The procedure you mention is actually the code, in the compiler or interpreter, that resolves the name of an operation to its implementation for a given object type. It can be of the form you mention (exampel in Scheme): (define (some-class variable1 variable2 variable3 ...) (letrec ( (method1 (lambda (...) ...)) (method2 (lambda (...) ...)) (method3 (lambda (...) ...)) ... (self (lambda message ; the function/type overload resolver (case (head message) ('variable1 variable1) ('variable2 variable2) ('variable3 variable3) ('... ...) ('method1 (apply method1 (rest message))) ('method2 (apply method2 (rest message))) ('... ...))))) ; return the closure which is the object self)) (set! an-instance (some-class ... ... ...)) (an-instance 'method1 ...) This is almost equivalent (modulo the fact these have manifest types and by default do overload resolution at compiletime) to the Simula 67: CLASS some_class(variable1,variable2,variable3); ... variable1; ... variable2; ... variable3; ... PROCEDURE method1(...) ....; ... PROCEDURE method2(...) ....; ... PROCEDURE method3(...) ....; BEGIN COMMENT overload resolution done by the compiler; END some-class; REF (some_class) an_instance; an_instance :- NEW some_class(...,...,...); an_instance.method1(...); and of the C++: class some_class { public: ... variable1; ... variable2; ... variable3; ... ... method1(...) { ... }; ... method2(...) { ... }; ... method3(...) { ... }; ... some_class(...,...,...) : variable1(...), variable2(...), variable3(...) { /* overload resolution done by the compiler */ }; }; some_class an_instance(...,...,...); an_instance.method1(...); Anybody can easily add a Smalltalk version, and so on. I hope that all this is clear not just to Margolin and company. Please, please note that the bodies of the methods are in all three cases lexically closed with respect to the names of instance variables and of the methods themselves, and that this is *necessary*. If method bodies are not bound lexically in the closure which is the object, things will not work. As to overloading resolution, the lambda in the Scheme version, which is the overloading resolutor, can be easily factored out at compile time if '(head message)' is statically known (the default case in C++ and Simula 67, for example, and a clever Scheme compiler can easily do that from the above definition), or it can be implemented as a general purpose function/type dispatcher that can resolve overloadings at run time (as in CLOS, for example). In the latter case overloading resolution is entirely different from dynamic scoping; in CLOS overloading resolution is done on the types of multiple objects, which is so clearly different in nature from scoping. With a little syntactic sugaring one can make the overload resolver above implicit in the definition of a class in Scheme too. Margolin will not need it, but some unbelievers :-) may well check Abelson & Sussman, which give ample examples of all this, syntactic sugaring included. It is IMNHO obvious that all non actor based OO implementations are shaped like above, irrespective of whether the operator resolution is code is in the compiler or in the interepreter, and that all the methods of a class *must* be lexically closed with respect to the members and methods of the same class, if at all; CLOS does not have member methods, so it does not need to close their namespace around that of the relevant class(es). Clear enough now? Can we get on to serious discussion like about the merits of important things like the OO decomposition paradigm and its strenghts and limitations? -- Piercarlo Grandi | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk