Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!cs.utexas.edu!tut.cis.ohio-state.edu!pt.cs.cmu.edu!dsl.pitt.edu!pitt!willett!dwp From: dwp@willett.pgh.pa.us (Doug Philips) Newsgroups: comp.lang.forth Subject: Re: ... and zen there were objects. Message-ID: <1569.UUL1.3#5129@willett.pgh.pa.us> Date: 23 Aug 90 00:53:31 GMT References: <11425@medusa.cs.purdue.edu> Organization: String, Scotch tape, and Paperclips. (in Pgh, PA) Lines: 154 In <11423@medusa.cs.purdue.edu>, bouma@cs.purdue.EDU (William J. Bouma) writes: > In article <28039@nigel.ee.udel.edu> carroll@udel.edu (Mark Carroll ) writes: > On the contrary, I think our disagreement is actually very small. We are > just approaching this from different directions, different backgrounds. > What I want to do is add some interesting low-level features to the > language in the best, most implementable way. Then let the user decide > how to use and view them. Of course I have in mind the OO view in building > the features inititialy, but if the programmer chooses to view them a > different way, fine. Aha! This is quite different than wanting to OO (right) from the start. Now that some of the secret agendas are on the table we can perhaps make progress. > But you want to decide what things should look like at the top level, and > then impose that view on the language at whatever the implementation cost. > I have just been saying that this does not coincide with the way forth > has traditionally been done. The way I see it forth has tried to be fast, > simple, and flexible always at the cost of what it looks like at the top. My impression has always been that Forth is supposed to GROW into the language with which you describe your solution. This is the first time I can remember hearing a Forth programmer advocating that the solution be bent towards Forth instead of the other way around. > >The benefits of object-oriented programming come from active objects. > >Indirect function calls are just implementation level details that make > >active objects possible. > > Ah, now we are getting somewhere! Indeed, see below. In <11425@medusa.cs.purdue.edu>, bouma@cs.purdue.EDU (William J. Bouma) writes: [ Quoted quotes: "> >" are now mine -dwp] > Yes, and I picked a level of abstraction appropriate to what I was > talking about, namely, implementing OO in forth. The person I was > replying to was trying to pull me to some higher level, saying that > I shouldn't look at OO that way as OO is really something much more > than that. Fine if it is, but that has nothing to do with what I was > talking about. Contemplating OO on some high level of abstraction is > not going to get it implemented. It seems like people think I have > something against OO just because I stoop to the level of implementation! No, the objection is that you are letting the implementation pollute the abstraction. Would you just as readily claim that the best way to implement stacks was with arrays, and therefore make stacks *look* like arrays, or even put arrayish things into them? I hope not. > > mechanism. Once you determine that all OOP is "really" is is indirect > > function calls, you *have* missed the point. CM and Wil Baden both have > If you think of it as something more than that when you are trying > to implement it you have really missed the point. How you implement it should not pollute how you use it! Were you to write a symbol table ADT, would you let the underlying lookup mechanism show through (i.e. AVL trees, hash tables, B-tree, etc?). Again, I hope not. "What" the ADT is should not be affected by "how" it happens to be implemented in some particular instance. > As far as I know indirect function call is the only way. Please tell me > some other way. I really would love to talk something solid here rather > than this silly bickering over word semantics. It is easy to see that > writing if-then statements on the fly isn't going to work. I consider > indirect jump equivalent to indirect function call, don't you? [I consider indirect jump equivalent, for the sake of the current discussion.]. Actually, I fail to see how you can avoid a chain of if-then statements. If you have active messages and passive objects, as you have been advocating, then message names are words that must be known globally. That implies that the set of message names understood by a class of objects is not necessarily going to be contiguous. That means you are going to have to search for the method that implements the message. You could easily have something like this: (Rough, off the cuff, proof-of-concept sketch follows:) \ Ignore multiple/single inheretance for clarity of example. \ for every method described here, SELF is a word that puts the receiver \ of the message onto the stack. \ Instance variables can be declared after the CLASS and before the \ first METHOD, but that doesn't affect what we're doing here. CLASS Foo METHOD m1 ( code for method m1. ) METHOD m2 ( ... ) METHOD m3 ( ... ) ENDCLASS The above code can compile into a series of if-then tests, much like Wavrik's recently posted IF( )IF might. The SEND method (in my scheme) pops the object, arranges for it to be the result of SELF, which leaves the message name on the top of stack. It then jumps to the if-then code above (based on information gotten from the object). The code then figures out which method to invoke, if it finds one, it executes it and returns. If the code falls through to ENDCLASS, ENDCLASS could arrange for a search of the super-classes dictionary, or whatever. You have the above Forth code compile all the methods and then generate a vector of indirect addresses. That table would still have to be searched. You might even flatten the table so that it includes the addresses of the superclass(es) methods that aren't eliminated or over-ridden. You *might* even keep a table per message and look up object types in it. Of course every class (object type) isn't going to implement every message, so you'll have to provide large tables or search compacted ones. If you allow the classes to dynamicly change the methods for their messages that may effect the way you choose to implement SENDs. None of these alternatives should affect the way you *use* OOP in Forth. Nor should you pick a OOP Forth extension that forces you to use one of those implementation strategies. This is also why the X3J14 TC will *not* prescribe how a dictionary is to be implemented. It just doesn't matter. If you need to hack your particular implementation for dictionaries for some reason, you can. Doing -FIND or EXECUTE or whatever can all be done, efficiently, by whatever kind of dictionary implementation you have, without you *having* to know what that implementation is. > But if I am to write an OO language, I MUST specify the mechanism by > which it works! If I do not focus on such a low level detail, I will not > have any OO to reap the benefits from! *How* you implement it is obviously constrained by *what* you implement. *What* you implement should not be constrained by *How* you think it should be implemented on machine X at point in time Y. You *may* decide that you cannot implement the full ADT because it would be just too expensive to be used. I have not seen anything like that kind of argument or analysis here. What you seem to be saying is: I can only imagine that OOF is implemented by using indirect function calls. Therefore, there is no reason to hide that fact from the OOF extensions. > You consider a single SWAP an ugly stack game? You should not be > programming in forth. No, I think inconsistency is ugly. In order to do delayed sends you are going to have to play stack manipulation games. In your scheme you write delayed sends differently because you have no choice. In my scheme, delayed sends are easily accomplished by controlling when SEND is executed. I claim that my way is more consistent, is simpler, and is still in the spirit of Forth. I consider having to do SWAP EXECUTE ugly. It is gratuitous stack manipulation. I think that gratuitous stack manipulation is ugly. I also think it indicates that the factoring involved is not as good as it could be. Look, you can probably use method-active OOF and get away with it for a majority of your OOF needs. Personally I think it is flawed. I would rather have a *real* OOF. Even if you only notice the difference 5% or 10% of the time. If we (the royal we) are to take up Mikael Patel's challange to build a good OOF and then start to build a library of objects on top of it, I would really like to see that that effort is not hamhocked by an ill-chosen OOF base. In reality, I don't know that any of this matters. I will not write a line of object or message active OOF. I will first do it right. I may be the only person to think this way. Perhaps the beauty of Forth is that that doesn't matter. -Doug --- Preferred: ( dwp@willett.pgh.pa.us OR ...!{sei,pitt}!willett!dwp ) Daily: ...!{uunet,nfsun}!willett!dwp [last resort: dwp@vega.fac.cs.cmu.edu]