----- Mike
IMHO any language can be used for OOP, but again, that's only *MHO*.
>What do you think of Smalltalk as compared to FORTH? I think it is
>just a more readeable version of FORTH! :-)
From an implementation point of view (I've implemented both), they are very
close in that they both use threaded code interpreters (vitual machines),
which is token threaded in Smalltalk's case. The virtual machines are both
stack machines. Most Forths support multitasking and all Smalltalks do.
It would be trivial to write a forth-like user interface for Smalltalk.
However there are major differences, with Smalltalk being much more complex
and sophisticated. Some differences:
1. Smalltalk has dynamic memory management and garbage collection.
2. Smalltalk data is typed.
3. Smalltalk does late binding, and this process is part of the virtual
machine.
4. Smalltalk virtual machine supports local variables and arrays.
5. Smalltalk virtual machine supports graphics, with sophisticated graphical
primitives.
The Smalltalk interpreter kernel I wrote (for 80386 protected mode) came to
about 64k of code, about half of that assembler, and the other half in C.
Size with "image" (equivalent to Forth dictionary) was about 1 megabyte.
--
Tom Almy
tom....@tek.com
Standard Disclaimers Apply
For some people might be. But I need the low level features of FORTH.
(I personally love OOP but I designed one for myself.)
Why is Smalltalk 'more readable'????
Andras
Ok, I'll bite. Why do you think FORTH is OOP, and enough
OOP to compare to Smalltalk? Why do you think FORTH and
Smalltalk have similarities?
--
Darin Johnson
djoh...@ucsd.edu
- I'm not a well adjusted person, but I play one on the net.
I don't know which one I like better, yet, but Smalltalk seems more
readeable - that is an advantage. The syntax is "easier" - FORTH syntax
is in outer space. :-) Having Words or a browseable library seems kind
of the same to me - just 2 ways of doing OOP. OOP is really just small
chunks of code, subroutines etc... You can do the same thing in FORTRAN,
but there is nothing to make you do this, where FORTH and Smalltalk
have OOP built in, in my opinion. FORTH is probably more efficient,
since it will run in a miniscule RAM and DISK space on a machine.
The RPN of FORTH helps FORTH be compact, since the programmer is
doing part of the work. I have heard that both are a bitch to learn
from many people - I have played with FORTH on and off, but have just
started looking at Smalltalk. Just ordered DIGITALK Smalltalk V for
DOS. I used to have Atari 8-bit ValFORTH - Super product! In fact,
I attempted to get my last organization interested in Pocket FORTH for
the Mac, but didn't try too hard, since they would think I was out of
my mind :-) It actually is more powerful than your $1000 Macintosh
development systems, in many cases. But, not to be rambling, I
think the essence of OOP is having a way to EASILY reuse Code.
All this Inheritence, Polymorphism, and all the other OOP buzz words
that are thrown around don't mean squat if the software is hard to
use and learn...
---- Mike
... stuff deleted
>I don't know which one I like better, yet, but Smalltalk seems more
>is in outer space. :-) Having Words or a browseable library seems kind
>of the same to me - just 2 ways of doing OOP. OOP is really just small
>chunks of code, subroutines etc... You can do the same thing in FORTRAN,
... stuff deleted
>development systems, in many cases. But, not to be rambling, I
>think the essence of OOP is having a way to EASILY reuse Code.
>All this Inheritence, Polymorphism, and all the other OOP buzz words
>that are thrown around don't mean squat if the software is hard to
>use and learn...
>
If you mean with ``objects'' in OOP just bits of code, you are right, but
usually ``objects'' are conceptual units that have some kind of relation to
the real world. Encapsulation of an objects properties and it's actions
(data and code) into one unit is one aspect of OOP, class mechanisms: e.g.
instantiation operation and inheritance another: you want to be able to
start with a general class and build individual instances from that generic
concept, and you want to be able to specialize you generic concepts into
particular ones.
These mechanisms have been invented to make it easier on the programmer to
use consistent concepts and mechanisms throughout a large program, that has
something to represent in the real world.
I don't think you can ``do the same thing in FORTRAN'' since none of the
mechanisms mentioned: encapsulation, instantiation, inheritance, are
available in FORTRAN or Forth I don't consider them to be OO languages.
Forth, of course can be coerced into anything, but object orientation is not
a Forth built-in.
- Josef
I have never understood why CREATE DOES> constructs have not been accepted
as a form of OOP. CREADE DOES> constructs encapsulate the code that
operates on a data structure with the data structure, and
creates new instances of these structures that inherit the
code that operates on the data. New code (methods) can be added
as new classes words are built up from basic classes, they inherit
the data structure and code from the parent class and allow you
to add more and encapsulate it in a new class.
>These mechanisms have been invented to make it easier on the programmer to
>use consistent concepts and mechanisms throughout a large program, that has
>something to represent in the real world.
This is Forth style as well even if you do not argue that is OOP.
>I don't think you can ``do the same thing in FORTRAN'' since none of the
>mechanisms mentioned: encapsulation, instantiation, inheritance, are
>available in FORTRAN or Forth I don't consider them to be OO languages.
>Forth, of course can be coerced into anything, but object orientation is not
>a Forth built-in.
>
>- Josef
FORTRAN doesn't have CREATE DOES>, Forth does, and it has had something
like it for a very long time. When I describe CREATE DOES> I often use
the encapsulate instantiate inherit description rather than talking
about the compile time vs run time behavior of words that define words
that define words...
There are various approaches to doing OOP in Forth, but no standards.
People have used mechanisms like multiple wordlists to permit operataor
overloading etc to make Forth look more like other OOP environments. But
I would argue Forth is already got the original OOP tools built in.
Jeff Fox
Ultra Technology
>I have never understood why CREATE DOES> constructs have not been accepted
>as a form of OOP. CREADE DOES> constructs encapsulate the code that
>operates on a data structure with the data structure, and
>creates new instances of these structures that inherit the
>code that operates on the data.
*I've* accepted it as a form of OOP, and I used to teach CREATE DOES> in
that manner (with a very high success rate of quick understanding, I might
add!)
However compaired to modern OOP languages, its quite limited. You can only
associate one piece of code (method) with any object class, namely the code
that gets executed when the object is executed. There is no concept of
multiple methods or message passing as a means to implement it. It can be
done (and I've done so), however it's not a part of basic Forth.
>New code (methods) can be added
>as new classes words are built up from basic classes, they inherit
>the data structure and code from the parent class and allow you
>to add more and encapsulate it in a new class.
Well, yes for a typical OOPL, but not for Forth. How do you do subclassing
with CREATE DOES>?
If you want ``built-in'' OOP you must use Smalltalk or something similar.
Even in C++ OOP is an ``add-on'' to C (it's not a flame-bait!) not to
mention other OOP languages such as Turbo Pascal which can be used without
any OOP.
You can do the same thing in FORTH but it would be very hard to implement
an OOP in a FORTRAN compiler.
(Of course I am not talking about the ANSI FORTH here.)
Andras
That's only part of OOP. Basically this just gives you data
encapsulation.
Here's some things I think an OOP needs to be called that.
Your opinion may vary (in fact, C++ only barely meets my
criteria, yet the general masses accept that as the de-facto
standard of what OOP is).
- Data encapsulation. Ie, separate the interface from the
implementation. Users of the data must only use the
provided abstraction. Most non-OOP languages allow this
in some form.
- Hierarchy. Objects (a logical entity that encapsulates
data) are arranged in a hierarchy. Parent/child relations
and so forth.
- Polymorphism and overloading. This is the big clincher.
This means that the same operation will work on
many different types, with the exact operation determined
by the objects type. A subclass of an object will take the
same operations as the superclass.
This last is where the default Forth falls down. In Forth,
the center of attention is the word, which is the operation,
and not on the data. A "+" doesn't work on non-integers
or other types. By default, you can't have "list 3 insert" and
"sortedlist 3 insert" both work if list and sortedlist have
different layouts.
This isn't to say you can't add all this stuff to Forth. An object
type can push a pointer to a vector of operations and methods on that
object will be indirected (easy to do in other non-OOP languages).
Add an inheritance scheme to this (harder to do in other non-OOP
languages) and you've got "Forth with OO extensions". But that's a
lot more than "CREATE DOES> is a form of OOP".
--
Darin Johnson
djoh...@ucsd.edu
Caution! Under no circumstances confuse the mesh with the
interleave operator, except under confusing circumstances!
> \ snip \
>However compaired to modern OOP languages, its quite limited. You can only
>associate one piece of code (method) with any object class, namely the code
>that gets executed when the object is executed. There is no concept of
>multiple methods or message passing as a means to implement it. It can be
>done (and I've done so), however it's not a part of basic Forth.
>
>>New code (methods) can be added
>>as new classes words are built up from basic classes, they inherit
>>the data structure and code from the parent class and allow you
>>to add more and encapsulate it in a new class.
>
>Well, yes for a typical OOPL, but not for Forth. How do you do subclassing
>with CREATE DOES>?
>
>--
>Tom Almy
>tom....@tek.com
>Standard Disclaimers Apply
If the DOES> part of a definition ends in NOP it can be hot patched, or
if an execution vector to NOP is used then new code can be added to
derived classes. There will always be a stub on which to attach more
code. Each CREATED word will have its own copy of data, so it can
have its own vector to its own code to distinguish it from other
derived classes. Does that qualify as OOP in your opinion?
Jeff Fox
Or rather, in forth, message passing is factored out of the object
methodology. To implement an object with multiple methods you need to
explicitly include the message passing mechanism.
--
Raul D. Miller N=:((*/pq)&|)@ NB. public e, y, n=:*/pq
<rock...@nova.umd.edu> P=:*N/@:# NB. */-.,e e.&factors t=:*/<:pq
1=t|e*d NB. (,-:<:)pq is four large primes, e medium
x-:d P,:y=:e P,:x NB. (d P,:y)-:D P*:N^:(i.#D)y [. D=:|.@#.d
Ok, so do we agree that CREATE DOES> does this? Or at least that
it can do this?
>- Hierarchy. Objects (a logical entity that encapsulates
> data) are arranged in a hierarchy. Parent/child relations
> and so forth.
Ok, but if the DOES> code includes a mechanism to add new code
such as an execution vector in the data structure, then a
hierarchy is easily constructed.
>- Polymorphism and overloading. This is the big clincher.
> This means that the same operation will work on
> many different types, with the exact operation determined
> by the objects type. A subclass of an object will take the
> same operations as the superclass.
Yes polymorphism and overloading are not natural to Forth since
it is not strongly typed. But people who want to do this can,
using techniques that are standard Forth, but they are extending
Forth with things it normally does not have. After all in Forth
nomally the programmer must choose the correct operator for
the type of data. A "+" does not normally add doubles or add an
item to a list etc. Pountain does it with control over the search
order so that the correct "+" will be used. But I agree this is
may be the biggest deviation from normal Forth style.
>This last is where the default Forth falls down. In Forth,
>the center of attention is the word, which is the operation,
>and not on the data. A "+" doesn't work on non-integers
>or other types. By default, you can't have "list 3 insert" and
>"sortedlist 3 insert" both work if list and sortedlist have
>different layouts.
Well, "list" and "sortedlist" can inform "insert" about the data
type, and "insert" certainly COULD work on more than one data
type. Also "list" and "sortedlist" could also just set the
search order so that the correct "insert" is found. And I
would think there are other ways to make this all happen.
>This isn't to say you can't add all this stuff to Forth. An object
>type can push a pointer to a vector of operations and methods on that
>object will be indirected (easy to do in other non-OOP languages).
>Add an inheritance scheme to this (harder to do in other non-OOP
>languages) and you've got "Forth with OO extensions". But that's a
>lot more than "CREATE DOES> is a form of OOP".
>--
>Darin Johnson
>djoh...@ucsd.edu
Well I think we are pretty much in agreement. It seems like you
are saying CREATE DOES> only gives you 1/3 of OOP but you can do
the rest with other stuff if you want to extend Forth to a more
conventional OO language. I guess I am saying that it seems to
me that CREATE DOES> gives you 2/3 of OOP in the conventional
sense, and that you don't need much more. ( does a programmer
really need "+" to do everything that it does in English?)
Sure CREATE DOES> is not used by all Forth programmers, and
most Forth programmers are not trying to do OOP. But I think
that the third point about Polymorphism and Overloading IS a
feature of Smalltalk that doesn't match directly to standard
Forth. But you certainly can get Polymorphism and Overloading
if you want them. I see it as more of an issue of design.
I think that this last point is one of the weaknesses of OOP
in that it focuses on trying to create general solutions to
everything and then more from there to more specific solutions.
It can result in excessive factoring into too many classes and
result in a big performance overhead.
To me it is part of the mentality that the only way to create
applications is to build on top of a library that includes a
general purpose solution to every imaginable problem. After
all as you will read in the popular press today that with all the
room on CD-ROM there is no reason that all applications will
not soon be distributed on full CD-ROM. Every possible
variation in the configuration can just be included as a
separate EXE file. And it doesn't matter if a "hello world"
program needs a few hundred megabytes of library files.
I once asked Chuck how it was that OKAD could be 1000 times
smaller and faster than some other VLSI CAD software. After all
you rarely see Forth programmers claiming that they can write
applications that are 1000 times smaller and faster than C.
His answer was "focus on the problem at hand and don't solve the
general case if you don't need to."
People will argue that C++ or Object Oriented Forth is not "real
OOP" like Smalltalk. It depends on who you talk to. Whether
CREATE DOES> provides 1/3 of OOP or 2/3 or enough to call it OOP
will depend on who you ask. So a lot depends on your definition
of terms. If you accept that Smalltalk is the definition then
C++ doesn't quite cut it.
So Darin may be right, and I think his view is more generally
accepted than mine. But to me 2/3 is enough to call it OOP even
though the purist definitions and mine may not always agree.
Jeff Fox
Ultra Technology
It is all good and nice, but I don't feel an 'OOP' serious without late binding
and CREATE DOES> just cant do it (in itself).
Andras
Perhaps you could give an example. The example that appears most in
the literature (on abstract data types) is a stack -- not particularly
interesting but it does show all the necessary features. All you need
to do is define the interface (new, push, pop, top ... etc.) and give
two or more implementations of it (say linked list and a automatically
resizing array).
... Ok, but if the DOES> code includes a mechanism to add new code
such as an execution vector in the data structure, then a
hierarchy is easily constructed. ...
How is that different from saying that C includes a mechanism to allow
yout to embed function pointers in a structure and hence a hierarchy
is easily (sic) constructed?
Mike Winters writes:
> I am convinced that FORTH was probably the first real OOP language.
and later:
> I think the essence of OOP is having a way to EASILY reuse Code.
> All this Inheritence, Polymorphism, and all the other OOP buzz words
> that are thrown around don't mean squat if the software is hard to
> use and learn...
Having worked with Forth, C, Pascal, etc. and OO-languages,
imho the essence of the paradigm of OO is to work in three phases:
1) OOA i.e. OOAnalysis i.e. Model the Problem
2) OOD i.e. OODesign i.e. Model the Solution
3) OOP i.e. OOProgramming i.e. Code the Solution
Only if you use all three of these phases of software construction you
will gain from the power and advantages of the OO-approach. Having
tried hard to teach the first two parts to many a student, it's
apparent that these are the stages that are hard to grasp. It's a
fundmentally different way of looking at things. It's also factoring and
reuse but it's much more than that. It's reasoning about what objects
can be identified, what they 'know', what they can 'do' and what they
are responsible for. It's not easy to learn from scratch, especially
if you are deeply rooted in more traditional ways of writing software.
But - no pain, no gain - it's very much worth the effort once you
understand the principles and are able to solve problems in a most
convenient and comforting way.
Tom Almy writes:
> IMHO any language can be used for OOP, but again, that's only *MHO*.
Granted, you could do the last phase, the OOP, the implementation in
any old language, even assembler, but once you have put so much work
into the first steps, you choose a language that supports best the
design you have created. Unfortunately, neither Forth nor C or
Fortran do support you this way.
But true OO languages such as Smalltalk or MOON do reflect your design
straightforward in the code. Which means that the runtime-system takes
most of the burden off your back and lets you concentrate on the
design.
By the way, it's surely great to be able to do everything yourself,
but it's surely a pain in the arm to have to do everything yourself!
I agree with most of what Tom Almy writes on Smalltalk, but not with:
> 2. Smalltalk data is typed.
To my understanding, Smalltalk is fully OO but not at all typed. In a
typed languages, type mismatches can be caught at compiletime. In a
non-typed language such as Smalltalk or Forth, type mismatches can be
found only at runtime, causing an error-message or unexpected results.
However, have been approaches to a typed Smalltalk, such as TS by Johnson
and Graver, Univ. of Illinois or ST&T from Imperial College, London, UK.
In case you never heard of the Forth-based, strongly typed OO-language MOON,
I presented it on euroForth conferences 1992, 1993, 1994 and in more
detail in FD XIV/1 and XV/2.
Any comments on the concept, on its Forth-ness, on the implementation,
etc. are more than welcome.
Markus
-------------------------------------------------------------------------------
Markus Dahm mail: da...@rwth-aachen.de MOON
Lehrstuhl fuer Messtechnik phone: +49 241 80 7864 and
RWTH Aachen fax: +49 241 8888 200 more
[lots of stuff deleted]
>
>How is that different from saying that C includes a mechanism to allow
>yout to embed function pointers in a structure and hence a hierarchy
>is easily (sic) constructed?
I don't think there is much difference at all. I've seen versions of
C++ that just use a pre-processor to convert C++ code to C with weird
union names and such.
If you want to claim that C++ is not OO, that's fine with me.
--
/ ------------------------------------------------------------------------ \
/ Mark Flacy "There's a lot to be said for a blow to the head" \
/ fl...@eecs.umich.edu - Blue Oyster Cult \
/ "I guess ya had to be there." - Me \
If you definition of "serious OOP" requires late binding it is very
easy to tack on. Sure the CREATE DOES> doesn't do late binding.
Late binding is one way to deal with operator overloading, since
it is at run time that an object decides which method is appropriate.
Personally I have never appreciated lated binding. If the appropriate
action can be determined at compile time then the run time performance
is improved. :-)
Not everyone agrees that late binding is essential to OOP. It does
depend on your definition.
I am NOT saying that CREATE DOES> give you everything that you get
in Smalltalk. And if Smalltalk IS the defintion of "serious OOP"
then CREATE DOES> is not.
Forth is usually a small amount of code poised to take off in any
of a number of different directions. Some users never use
CREATE DOES> and others use it constantly. Some programmers use
Object Oriented approaches others do not. I am not saying that
CREATE DOES> is exactly the same as the inner workings of Smalltalk
or C++, only that it seems to me to provide the framework for
what are the essential features of OOP to me, that being
encapsulation, instanciation, and inheritance. I don't include
late binding as essential, but you can add it into the CREATE DOES>
constructs if you wish.
Jeff Fox
Ultra Technology
Right... ?
Most languages aren't judged upon a single construct. In the case of
Forth, there are other words to deal with late binding. Which would
imply that while Forth might be considered an object oriented
language, CREATE DOES> considered alone would not be.
Which seems a rather unsuprising conclusion.
Hmm, I think most people out there would disagree that code
reuse is the essence of OOP. It's an advantage, but that's
not the same thing. It's very easy to have something distinctly
non-OO, yet be very good at code reuse.
What does make for OOP are those buzzwords that you threw out!
They may not mean squat if the software is hard to use and
learn, but they can still mean OOP.
I think your problem here is the buzzword syndrome. Ie, you
hear a lot that OO is great, and you don't want to admit that
your favorite language is not OOP. Therefore you claim that
it is, and justify this by molding your own definition (granted
the OOP definition isn't clear cut, but...) But not to worry,
most of industry does this as well!
As far as what is OOP or not, back in grad school a prof had
a way of looking at this that was much more appropriate than
the common "is/isn't" approach. Instead languages can
"enable", "support", or "enforces" a language feature such
as OO programming.
"Enables" means that the language allows you to use something but
doesn't encourage or require it. Thus, you can program in an OO style
in Forth or C, but you don't get any help at it. "Support" means
that the language actually supports this by having features directly
related to this. For instance, C++ has support for OOP. "Enforces"
means that this feature or paradigm is pervasive. Smalltalk enforces
OOP, since you can't get around it. C++ doesn't enforce OOP since
you can just use normal C features.
> > IMHO any language can be used for OOP, but again, that's only *MHO*.
Well then, you don't get much by saying Forth is OOP if you can
also say it about assembler and Fortran :-)
> > 2. Smalltalk data is typed.
>
> To my understanding, Smalltalk is fully OO but not at all typed. In a
> typed languages, type mismatches can be caught at compiletime.
It's typed, but in a different sense than what you get in Ada or such.
All objects have a distinct and immutable type (compare to C where
objects don't have a fixed type and can be cast at will without
conversion). But it doesn't have compile time type checking.
However, you also don't often have the problem of passing a number and
have the receiving end confuse it with a string. These two "typing"
things are very different, but since the same term is given for both,
it can get confusing.
--
Darin Johnson
djoh...@ucsd.edu
Support your right to own gnus.
No.
1 - NOP only allows hot patching with certain Forth implementations.
2 - Linking code together doesn't solve the problem, you are still stuck
with only one method for any object. Just consider the "simple" problem
of being able to print all objects. If the DOES> part of the defining
word prints, then you can't use the defined word for anything other
than printing. Conversely, if the DOES> part does data referencing
(which is typical), then it can't print. Show me an implementation of
arrays using DOES> which will handle printing the array contents.
You can do OOP in Forth. You can also do OOP in C, Assembler, Fortran, ...
However none of these languages are designed specifically for OOP. None
of the qualities in the Smalltalk interpreter engine which are present for
implementing the OOP functionality are in Forth. And likewise, there
is nothing like Forth's CREATE..DOES> in Smalltalk.
>Or rather, in forth, message passing is factored out of the object
>methodology.
You are being too kind! They were never in Forth's methodology to be factored
out in the first place. :-)
Mr. Pountain's book contains several interesting ideas for the use
of defining words and management of the dictionary space to provide
true OOP. In fact, this was the first book I found in which the
power of CREATE DOES was really brought home to me. It was, to me,
a much better treatise on FORTH than the "Starting FORTH" series.
Is Mr. Pountain (sp?) still active in the FORTH arena? It strikes
me that he could contribute significantly to this discussion.
--
- Mark Clark
> By the way, it's surely great to be able to do everything yourself,
>but it's surely a pain in the arm to have to do everything yourself!
We have implemented pretty extensive true OOP tools in our EXPRESS
industrial software package (runs on polyFORTH), including a number of
classes of objects for I/O and data structures, a class-based data base
toolkit and other stuff. Encapsulated data, methods,
operator-overloading, etc. It's really very straightforward to add this
stuff to Forth.
Some folks here have somehow cavilled at the notion of add-ons: "then
it's no longer standard Forth..." But the whole point of Forth is its
extensibility -- programming *is* adding on to the basic system the
capabilities you need to solve a problem. If you want to do-it-yerself
that's ok if you have the time, or you can buy it. Most serious Forth
vendors are doing OO stuff these days, each according to the perceived
needs of their favorite market!
Indeed. But there are important cases, where the action can't be
determined at compile time. Think of a GUI. Your dialog box is
composed of a number of different GUI element boxes, certainly
with objects of different classes. Your mouse handler send a message
to one of the object, that it has been clicked. Now, can you determine
at compile time, which object was hit?
>Not everyone agrees that late binding is essential to OOP. It does
>depend on your definition.
IMHO late binding is essential. OOP without it is toy OOP. You can't do
anything useful with it. You could create hyphenated words instead.
I don't expect that an OOP language provides multiple inheritance.
Single inheritance is enough.
>I am NOT saying that CREATE DOES> give you everything that you get
>in Smalltalk. And if Smalltalk IS the defintion of "serious OOP"
>then CREATE DOES> is not.
It is not necessarily all Smalltalk provides, but it should be a
considerably large amount of that. CREATE DOES> is the first step
from procedural programing towards OOP. The _first step_. No more.
>Forth is usually a small amount of code poised to take off in any
>of a number of different directions.
Well, it takes about a gross lines (a doezend doezends - in Forth this is
usually 256 :-) to turn a Forth into a real OOP with late binding,
polymorphism and some primitive kind of dynamic memory allocation.
--
Bernd Paysan
"Late answers are wrong answers!"
<A HREF=http://www.informatik.tu-muenchen.de/cgi-bin/nph-gateway/hphalle2/~paysan/>My Homepage</A>
To my understanding, Smalltalk is fully OO but not at all typed. In a
typed languages, type mismatches can be caught at compiletime.
I think you are confusing typing with static typing. IMHO Smalltalk
is strongly typed (every object has a type, though not necessarily a
-static- type) whereas Forth isn't. Note just to try and avoid any
misunderstandings I'm -not- implying that "strong" == "good" ... etc.
In case you never heard of the Forth-based, strongly typed OO-language MOON,
I presented it on euroForth conferences 1992, 1993, 1994 and in more
detail in FD XIV/1 and XV/2.
Now for the famous usenet question: is there anything on MOON
available online?
Caveat: the important word there is "if". Many times the appropriate
action can not be determined at compile time.
For instance, if you want every object to have a "print" function,
and at some point in your code you are receiving an anonymous
object whose exact type is not known (although a superclass may
be known), early binding will have serious troubles.
> Not everyone agrees that late binding is essential to OOP. It does
> depend on your definition.
Well, generally, it was generally accepted until people started
using some late binding systems and wanted to call them OOP :-)
> I am not saying that
> CREATE DOES> is exactly the same as the inner workings of Smalltalk
> or C++, only that it seems to me to provide the framework for
> what are the essential features of OOP to me, that being
> encapsulation, instanciation, and inheritance.
Ok, show us an OOP program done using basic CREATE DOES> (no fair
setting up an array of code vectors for each object. With or
without late binding.
Why no code vectors? You're interested in alternative
implementations?
If such systems are pre-processors then isn't a C compiler just a
"pre-processor" that produces assembly?
If you want to claim that C++ is not OO, that's fine with me.
I didn't make any claims; I asked why embedding funciton pointers in
Forth is OO, but embedding function pointers in C is not considered to
be.
C doesn't allow as much compile-time control over expression.
In Forth, strongly typed polymorphism is a LOAD file away. C's
#include files don't provide that kind of flexibility.
Granted, C is "more portable" than Forth. That's a cultural issue,
however.
Because once you get a nice general scheme with that, you've
basically got a Forth with OOP extensions. The original contention
wasn't that Forth couldn't be extended that way, but that Forth
was already OOP. (and caused by the fact that CREATE DOES> was
something mystical)
Actually, I take it back. Do it with code vectors if you want,
but make it clean, general, and easy to use, including subclassing.
Just getting it done is straight forward, but if it can make it
nice, then you've got something.
--
Darin Johnson
djoh...@ucsd.edu -- Strange things are afoot at the circle-K...
Well, I'd agree if you can get your hands on the assembly listing...
(My point was that a C++ compiler that goes straight from C++ to
object code is a little harder to make than a C++ to C
processor. Which is one of those "duh" observations that I've been
known to make...)
> If you want to claim that C++ is not OO, that's fine with me.
>
>I didn't make any claims; I asked why embedding funciton pointers in
>Forth is OO, but embedding function pointers in C is not considered to
>be.
I don't know why either. I think that it's a good question.
>However compaired to modern OOP languages, its quite limited. You can only
>associate one piece of code (method) with any object class, namely the code
>that gets executed when the object is executed. There is no concept of
>multiple methods or message passing as a means to implement it. It can be
>done (and I've done so), however it's not a part of basic Forth.
Your point being...? :)
The whole idea of 'basic Forth' is that it can be extended. Easily.
With all extensions having similar appearance to the 'basic' language.
BTW, what is 'basic' Forth? Never heard of it. If it doesn't allow
colon definitions it is pretty lousy.
>>New code (methods) can be added
>>as new classes words are built up from basic classes, they inherit
>>the data structure and code from the parent class and allow you
>>to add more and encapsulate it in a new class.
>Well, yes for a typical OOPL, but not for Forth. How do you do subclassing
>with CREATE DOES>?
Fairly simple. Get the file OBJECTS.TXT (or was it BLK?). That
implements single inheretance, message-passing in Forth. The resultant
code looks like this:
master object: vehicle
vehicle method: sit-there ;
vehicle object: car
car method: sit-there rust ;
Etc. It works well, but I fixed it a little more to handle things like
instance variables-- not neccesary, since a redefinition of object: will
do, but it works.
>Tom Almy
-Billy
Sold? :)
> I asked why embedding funciton pointers in
>Forth is OO, but embedding function pointers in C is not considered to
>be.
I have not had time to post the examples that were requested, but I would
l would like to clarify what I had to say about this.
I was talking about more than just embedding fuction pointers in Forth.
And I know that hot patching a NOP into a different function is not
portable. I was suggesting placing the execution vector for NOP into
one of the cells in the parameter area of a CREATE DOES> construct.
This vector can be executed in the DOES> part of the code, and each
class using the structure can extend the methods that work on the
data by appending portable execution lists into that vector.
Now C, doesn't doesn't normally include the C compiler in the app, or
have the ability to define words that define words that define words...
CREATE DOES> by itself can provide much of OOP, and can even be
extended to multiple inheritance schemes as I described above.
Using defered execution lists in the inherited instance of the parameter
area of a CREATE DOES> construct is not quite the same as embedding
function pointers in a C program.
Of course I am not saying that CREATE DOES> automatically gives you
operator overloading. You can do that with search order or message
passing if you want and you consider it an essential part of OOP.
Jeff Fox
In that point it goes to the C/Pascal/whatever vs. Forth argument.
You can implement OOP in any reasonably good language (say Pascal or C) so
of course you can do it in Forth. BUT the FIG/79-Standard/ANSI-FORTH does not
become and OOP language just because you can implement OOP in it.
(See C vs. C++)
Of course once you add and add-on OOP to Forth it will look 'more natural'
in Forth because Forth was designed for extensibility.
Andras
But CREATE DOES> is close to the equivalence of the macro
processor in C. Except that in Forth this can be done at
run time. That's the only advantage it gives you over C
as far as OOP. If you already have a class structure figured
out ahead of time (in the design process) then CREATE DOES>
hasn't bought you anything special over C. If you're tinkering
around, then you will get a bit of an advantage.
> CREATE DOES> by itself can provide much of OOP, and can even be
> extended to multiple inheritance schemes as I described above.
And C can't? Again, PLEASE PLEASE give an example of this. All
I've seen are a bunch of "we can do OOP in Forth, and do it better
than almost anything out there". These are backed up with low
tech arguments that indicate less of a knowledge of OOP than they
do the posters religious convictions on Forth.
--
Darin Johnson
djoh...@ucsd.edu -- Toy cows in Africa
You're confusing Forth's run time and compile time -- perhaps because
both are so short.
What you can do with CREATE DOES> is roughly analogous to (in C)
declaring a macro FOO(x) which builds a malloc'd obect (at compile
time) with arbitrary structure.
Here's a question for you: say I'm building a list data type in C++,
and I want to build it so that it "does the right thing" whether it's
allocated on the stack or on the heap (using new). In other words, I
want to decrement a reference count and destroy an object when it
reaches zero (if it's on the heap) or decrement a reference count and
pretend to destroy an object when it reaches zero (if it's on the
stack). The reason I want to do this is that I want to obtain
referential transparency, and use these lists as abstract data without
requiring any special knowledge of the quirks of C++.
Last time I was active with C++, this one hadn't been solved. Given
this lack of potential for a clean interface (and here I'm talking
basic facilities of the language), would you have said C++ is an
object oriented language?
Here's another one. In C, I have defined for myself an array type.
It's a variable sized array with a variable number of dimensions.
Elements must all be the same type, but they can be all arrays, all
numbers or all characters. So, I have a little specification that I
write that takes oh, maybe 15-20 characters defines a tree structure
built out of these arrays. Now, what additional work do I have to do
to instantiate this specific tree structure at compile time? [Assume
I have all the code to malloc and initialize the arrays at run time,
but I don't want to have to construct this thing every time I run my
program.]
That's the only advantage it gives you over C as far as OOP. If
you already have a class structure figured out ahead of time (in
the design process) then CREATE DOES> hasn't bought you anything
special over C. If you're tinkering around, then you will get a
bit of an advantage.
If you've already written the program, it shouldn't be to hard to
manually translate to some other language? This is some kind of win?
> CREATE DOES> by itself can provide much of OOP, and can even be
> extended to multiple inheritance schemes as I described above.
And C can't? Again, PLEASE PLEASE give an example of this.
I'll see if you can demolish my above two examples, first.
Out of curiosity, with regard to the discussion of Forth OOP
capability, suppose one were to add to the definition of the
language that it uses threaded code -- so that one could create
words which directly influence the compilation process and also
use "self-modifying" code and "hot patching" (which can actually
be made portable -- provided it is known that the code body of
a colon word consists of a sequence of addresses). To what extent
would this enhance the ability to produce object-oriented capability
in Forth?
The question is prompted by someone (I don't recall who) who mentioned
an then immediately dismissed the idea of "hot patching" as a tool
because it is "not portable". I'd be interested in hearing the
person involved go with the thought. Suppose that the potential
for changing addresses in existing code were made portable -- what
would this buy?
jjwa...@ucsd.edu John J Wavrik
Dept of Math - UCSD
Refer to the thread on FORTH chips to support my view (held for a long
time) that FORTH is an assembly language, just for a stack based
processor, as opposed to a register based (RISC) one.
In Risc assembly, you move the number standing for the type of object
into a register, then the start address of the instance of the object
you're going to be manipulating, then jump to the address of the procedure
you want to execute on the object, which jumps to the procedure
appropriate for that type of object. In an OO assembler (I dont think
one exists, so Im working on it myself), the assembler would insert the
address of the right procedure for the object, thereby eliminating the
detour through the 'completely general' procedure.
Depending on the OS and whether the object is one of the OS's base
classes or not, you might even move a number standing for the procedure
you want to use into a register, and do a system call (exception,
interrupt) instead of jumping.
On a FORTH chip, and even in FORTH, chip independent, I wonder if object
orientation could be implemented in that manner.
>I may be pointing out the obvious, but the most natural (from the point
>of view of the chip) way to write OO code is in assembly language.
Right, with the agreement that OO is as much programmer interface as it
is coding features.
>Refer to the thread on FORTH chips to support my view (held for a long
>time) that FORTH is an assembly language, just for a stack based
>processor, as opposed to a register based (RISC) one.
True. I had thought of it more as a natural language for computers. It
takes advantage of the computer's abilities and limitations, while
remaining 'speakable' to humans. (I wonder how that capability could be
improved on? Do you guys think it would be worthwhile to make a new
pronounciation and language for computer/human interface?)
>appropriate for that type of object. In an OO assembler (I dont think
>one exists, so Im working on it myself), the assembler would insert the
>address of the right procedure for the object, thereby eliminating the
>detour through the 'completely general' procedure.
The legendary Geos OS does usean OO assembler called 'Esp'. They
developed almost the whole OS in it, except the bootstraps (of course
:). It's Intel, but they're doing a C port. See comp.os.geos, and
download the GeoPublish demo-- help destroy MicroS-- MPH! ;)
(Sorry guys, got a little carried away there ;).
-Billy
PALADIN!
Personally, I don't think it affects that much. That's because
the same sorts of things can be done in other languages - except
that it is much harder to do or requires prior design.
>Suppose that the potential
> for changing addresses in existing code were made portable -- what
> would this buy?
Some very poor code.
BCNU, Gordon
John, as you well know, you are describing indirect threading. To make
portable this mechanism would require changing the ANSI standard that
we have (mostly) all agreed to live with to make a compilation mechanism
standard. Thus, Forths that use subroutine, token, or direct threading
--as well as those that compile directly to optimized machine code--
would not be "standard" any more. Since, for whatever reasons, indirect
threading is out of fashion just now, this would be a quixotic crusade.
Standardizing indirect threading would buy some ease and compactness
of programming: for example, jump tables would involve ] once again,
rather than sequences of ' , .
That is, an indirect-threaded compiler could be used in many ways not
initially intended by its designer.
I myself prefer indirect threading and am by no means convinced of the
advantages of direct- or subroutine-threaded Forths. At least one indirect
threaded one I use a lot is much faster than the subroutine-threaded F-PC.
If I hand optimize selected words in code, then the result is both shorter
than and at least as fast as, optimized C.
Nevertheless, it is always possible to "hot-patch", i.e. re-vector,
definitions in ANSI Forth, using CREATE ... DOES> . One allots space
for execution tokens and stores them in the appropriate place, then
employs @ EXECUTE to use them at run-time. Only very rarely does the
speed hit of this sort of indirection matter. As an example, we have
: NOOP ;
: USE( ' ;
: V: CREATE ['] NOOP , DOES> @ EXECUTE ;
: DEFINES ' >BODY STATE @
IF POSTPONE LITERAL POSTPONE !
ELSE ! THEN ; IMMEDIATE
\ Usage:
\
\ V: DUMMY \ create a dummy function
\
\ : )some_subroutine ( xt --)
\ DEFINES DUMMY \ hot patch xt to DUMMY
\ some steps
\ DUMMY \ execute whatever xt was on stack
\ more steps
\ DUMMY \ again
\ etc. ;
\
\ USE( FSQRT )some_subroutine
Why do things this way? Well, for one thing, it will work if
the phrase USE( FSQRT )some_subroutine is embedded in another
colon definition, rather than being invoked interactively.
In other words, ANSI gives us the tools to do such things, it is just
that they are not quite as simple as the old indirect-threaded methods.
--
Julian V. Noble
j...@virginia.edu
Refer to the thread on FORTH chips to support my view (held for a long
time) that FORTH is an assembly language, just for a stack based
processor, as opposed to a register based (RISC) one.
In Risc assembly, you can move the number standing for the type of object
into a register, then the start address of the instance of the object
you're going to be manipulating, then jump to the address of the
procedure type you want to execute on the object, which jumps to the
procedure appropriate for that type of object. In an OO assembler (I dont
think one exists, so Im working on it myself), the assembler would insert the
address of the right procedure for the object in the jump instruction,
thereby eliminating the detour through the 'completely general' procedure.
Depending on the OS and whether the object is one of the OS's base
classes or not, you might even move a number standing for the procedure
you want to use into a register, and do a system call (exception,
interrupt) instead of jumping.
On a FORTH chip, and even in FORTH, chip independent, I wonder if object
orientation could be implemented in that manner. After, the only
difference is, the registers are replaced by a stack in FORTH.
> : NOOP ;
Hmm...
Being relatively new to Forth I came up with a somewhat different
solution to generating vectored execution.
: USE ' ;
: FOR ' ! ;
Then you define some variable, lets say (EDIT). Then you need to define
a word to use the vector.
: EDIT ['] (EDIT) @ EXECUTE ;
Then simply typing EDIT will execute whatever word you entered for
vectoring. To setup up a word for vectored execution you would type
USE EDIT-BLOCK FOR (EDIT)
An interesting phenomena I have discovered when using this set of
definitions on PFE v0.99 (operating under OS/2 using emx) is that the
variable you use to hold the address of the word you are using (ie.
(EDIT) ) becomes primitive after executing the USE ... FOR ... command.
I don't pretend to know why this happens. That is why I had to use [']
in the definition of EDIT. You can redefine the vector as much as you
like and even use words such as EDIT inside other definitions. I
originally came up with this solution while writing a program to solve
Riemann sums and wanted to be able to alter the method used from
left-endpoint to mid-point, etc.
What do you think of this method for vectored execution, and is it "ANSI" ?
J Christopher Kennedy
kb7...@elwha.evergreen.edu
kb7...@io.com
Huh? An OO compiler for a RISC (or CISC) can't do this when
generating assembler code? OO doesn't belong at the assembler
level unless you have a specific OO architecture in mind.
Plus, once you abandon the 'completely general' procedure, you
abandon a lot of OO usefulness. What is the assembler going to
do if it doesn't know the object at assembly time?
And why is this discussion done at the assembler level instead
of the compiler level?
--
Darin Johnson
djoh...@ucsd.edu
- Grad school - just say no.
You make a mistake here! FOR does not store to the variable itself, but to
the place the execution token of the variable points to.
> Then you define some variable, lets say (EDIT). Then you need to
> define a word to use the vector.
>
> : EDIT ['] (EDIT) @ EXECUTE ;
>
> Then simply typing EDIT will execute whatever word you entered for
> vectoring. To setup up a word for vectored execution you would type
>
> USE EDIT-BLOCK FOR (EDIT)
>
> An interesting phenomena I have discovered when using this set of
> definitions on PFE v0.99 (operating under OS/2 using emx) is that the
> variable you use to hold the address of the word you are using (ie.
> (EDIT) ) becomes primitive after executing the USE ... FOR ...
> command. I don't pretend to know why this happens. That is why I had
> to use ['] in the definition of EDIT. You can redefine the vector as
> much as you like and even use words such as EDIT inside other
> definitions.
I can imagine what happens! Your FOR-definition patches the code of (EDIT)
and turns it from a variable to a primitive (I think because EDIT-BLOCK is
a primitive).
Perhaps you try
: FOR ' EXECUTE ! ; ( I'm not sure wether >BODY will be ok, too? )
: EDIT (EDIT) @ EXECUTE ;
> What do you think of this method for vectored execution, and is it
> "ANSI" ?
For you may not store into an execution token, it is not ANSI. But I
suppose what you did is not what you intended to do. I think you intention
fits to the standard.
- Joerg
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/ Joerg Plewe J...@Forth-eV.de _/
_/ Haarzopfer Str. 32, D-45472 Muelheim +49 (0)208 497068 _/
_/ Germany _/
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
I am not under the alkafluence of inkahol that some thinkle peep I am.
It is just the drunker I sit here the longer I get.
## CrossPoint v3.02 ##
This looks more to me like an attempt at distortion than a real question,
so I may be getting into trouble by trying to answer, but here goes:
CREATE DOES> constructs provide much of what is thought of by most people
as OOP. The CREATE DOES> construct provides encapsulation of data
structures and the code to operate on the data structures. Thus
a simple CREATE DOES> provides a way to create objects with instances
of the data structures and code to operate on them. However since the
code that is inherited by the created words will only get the "methods"
in the DOES> part. This does not provide a way to have parents and
children and classes that allow derived classes to have expanded
data structures and more methods.
This is easy to add to the CREATE DOES> construct however by leaving
stubs to extend the data area and method lists in derived classes.
This can be done in a portable or non-portable way as you wish.
I though Julian's post on the subject explained it pretty well.
But since you were refering to something I posted I though I might
give it a try.
> The question is prompted by someone (I don't recall who) who mentioned
> an then immediately dismissed the idea of "hot patching" as a tool
> because it is "not portable". I'd be interested in hearing the
Both the CREATE and DOES> part of the construct can contain a NOP
as a stub. If you know the type of threading this can easily
be "hot patched" to extend these fixed structures. However this
type of non-portable code is considered bad programmming style
by many. So rather than doing non-portable self-modifying
code such as hot-patching executable code, it can be done
in a portable way. An execution vector is stored in a variable or
in the parameter area in the CREATE part of the construct. The
DOES> construct then fetches and EXECUTEs the execution token to
provide a defered function.
You CAN do it (on some systems) with a hot patch but it is implementation
specific and not portable. But it is conceptually simple and on systems
where you can do it that way there may be no distiction between code and
data space. In ANS you cannot assume that these are in the same space
etc etc. SO if you want portable ANS code you should immediatly dismiss
idea of hot patches, and use EXECUTE.
> person involved go with the thought. Suppose that the potential
> for changing addresses in existing code were made portable -- what
> would this buy?
>
> jjwa...@ucsd.edu John J Wavrik
> Dept of Math - UCSD
Hot patching is not portable, but a defered execution vector in a
variable or parameter area is. It is a commonly used and very useful.
Vectored system output is a good example. You can direct it to the
console, a port, a file, a combination, or whatever in this way.
(from eForth) : EMIT ( c -- ) 'EMIT @ EXECUTE ;
So I hope I have made my thoughts more clear this time. I have no
interest in trying to defend someone else's description of what I
said. I did not say that CREATE DOES> gives you OOP because of
some mystical property. I did say that CREATE DOES> gives you
encapsulation of code and data, instantiation of data structures
and a single inherited method. And I did say that the CREATE DOES>
structure can be easily extended to include multiple methods and
extended data structures in a class hierarchy in either a portable
or a non-portable way. I also said that you can get polymorphism
and operator overloading with things like control of search order.
As I was listening to Andrew explain the details of the implementation
of the OO parts of win32forth I could not help but think of this
thread. C++ is not Smalltalk, neither is CREATE DOES> or
the OO stuff in Yerk, Mops, or win32forth. Is it OOP? It depends
on whom you ask.
I did not include a question about CREATE DOES> on the opinion
poll. Perhaps I should have. Some people never use it, some could
not live without it, and some consider it the basis of the OO
aspect of their code. :-)
I have been a little reluctant to jump back in on this thread as
it seems that rather than commenting on the examples that Julian
posted I have been asked to defend what seems to me to be a distortion
of what I originally said.
Jeff Fox
Ultra Technology
P.S.
With regard to ... suppose one were to ... so that one could ...
which ... and also ... which can actually ... provided that it is
known that ...
What would this prove? :-)
The last time you claimed this (a week or so ago?) I asked if you
could code up a stack as an example. If you posted the example could
you post/email it again (since I haven't seen it). If you didn't
could you give it a go sometime; to bastardise a well known saying "an
example is worth a thousand words."
: : NOOP ;
Please also see the paper "Dreams" in JFAR vol 6 no 4 pp 279-318, by R. J.
Brown, 1994. I wrote this paper to explain an OO system for Forth.
It is considerably different from Pountain's system, as all object binding
is deferred until execution time unless specifically overridden by a
keyword. In order to implementa prototype system to run this extendsion,
I used "hot patching" in LMI 386-UR/Forth, but as the article states,
there are ways to implement the extension in other threading techniques
as well. For multitasking systems, token threading seems to be the best
solution. I am currently working on a 32-bit 2's-compliment Unix/C++
implementation of an interpreter to run this OO extension to Forth
efficiently in a multi-threaded environment, with some unique ideas
added in to implement non-local exits (catch and throw) and some implications
to debugging.
r...@eli.wariat.org
r...@wariat.org (temporarily due to system upgrade in process on eli)
R. J. Brown
Elijah Laboratories Inc.
PO 833
Warsaw KY 41095
606 567-4613
: Huh? An OO compiler for a RISC (or CISC) can't do this when
: generating assembler code? OO doesn't belong at the assembler
: level unless you have a specific OO architecture in mind.
: Plus, once you abandon the 'completely general' procedure, you
See JFAR vol 6 no 4 pp 279-318 "Dreams" by R. J., Brown, 1994. This
paper describes an OO extension to Forth and also some OO hardware
features to make dynamic binding not incurr any execution time
overhead for references to dynamically bound objects. The hardware
is really simple, but I could envision OO assembler instructions for
it, although I really envisioned Forth as the machine language!
: abandon a lot of OO usefulness. What is the assembler going to
Indeed. What is overlooked in the equation of the DOES> word with OOP is
that while both allow a data structure to hold not only data but *methods*
for playing with the data, for it to be Object-Oriented would require a
(pretty complex) standard for doing so.
Let's try a stack with an initiator and three operations, push,
pop and displaying the top element without popping. Now, the actual
stack data SHOULD NOT be accessed by words using the stack object - that
is a violation of encapsulation. We can only access the stack data by
calling one of the three functions; this is our first stumbling block.
The question is, just how do you set up a CREATE .. DOES>
structure to handle multiple methods instead of just one? Well, it's not
hard to come up with any number of clever ways to do this, but remember:
it must be encapsulated to the point that users of your objects need not
understand the inner structure of them in order to use them. Okay:
1 CONST PUSH>STACK ( Constants refer to individual methods )
2 CONST POP>STACK
3 CONST TOP>STACK
: STACK ( size -- ) ( Data only accessed by DOES> code )
0 , DUP , 2* ALLOT ( Object holds # of elements in stack, )
( Total # possible, and a hunk o space )
DOES> ( command# -- ?varies? )
SWAP R>
R@ PUSH>STACK = IF ( If we wish to add to the stack... )
DUP DUP 2+ @ SWAP @ > IF ( If there's room )
DUP @ DUP 1+ ROT ! ( Update pointer )
2* 2+ 2+ ! ( store data )
ELSE ." STACK FULL, BOZO" 2DROP
THEN
ELSE ( If we wish to read from the stack... )
DUP @ DUP 0 > IF ( If there's stuff there )
R@ POP>STACK = IF ( If it's a destructive read )
2DUP 1- SWAP ! ( Decrement Stack Pointer )
THEN
2* 2+ + @ ( Fetch old top of stack )
ELSE ." STACK EMPTY, BOZO" DROP
THEN
R< DROP ;
NOTE!!!!! Firstly, this code is bad, as it is some time since I diddled with
Forth, and used a funky vocabulary. Secondly, it is bad because it assumes
that it will be called with a constant of 1, 2, or 3. Error handling is not
that relevant to the program structure - tweak it on your own.
You initialize a stack like so:
37 STACK BOB
To Create a stack of 37 integers. Pushing an 18 on the stack:
18 PUSH>STACK BOB
Either it works or you get an error message. Pop the top element onto the
'real' stack like so:
POP>STACK BOB
Reading the top element is TOP>STACK BOB. Dig? Now the real
problem is establishing a standard. You must tell people the names
of your methods (PUSH|POP|TOP>STACK), and pre/postconditions. Also
people have to agree on understandable names (like METHOD>OBJECT,
although that may not be ginchy with interpreters that only keep track
of the first few characters of a name. In that case, good luck with
OOP in general) that ensure that you're feeding a stack a stack
command - TOP>STACK rather than TOP>BANANA.
Is that a fair example? I don't want to even think about
how you'd do multiple inheritance and polymorphism. Yeeeeeeeeeee.
__ +--------------------+------------------------+
,ad8888ba, (88)| Today's likes: | Today's dislikes: |
d8"' -- `"8b `""'| | |
d8' "A Neo- | FORTH! | Smileys |
88 NEO-Retro- ,adPPYYba, :88 | Pentium FDIV jokes | Overuse of the word |
88 Techno- "" `Y8 :88 | Access Registers | "paradigm" by RPG's |
Y8, Fest!" ,adPPPPP88 :88 | Pointless likes | and OO-analysts |
Y8a. -- .a8P 88, ,88 :88 +--------------------+------------------------+
`"Y8888Y"' `"8bbdP"Y8 :88 | Question: If you could be an animal, |
,88 | what kind of animal would you be?|
88=z91...@mp.cs.niu.edu=88P; | Answer: A smart-aleck animal. |
http://I=still=hate=my=page' +---------------------------------------------+
>
> 1 CONST PUSH>STACK ( Constants refer to individual methods )
> 2 CONST POP>STACK
> 3 CONST TOP>STACK
>
> : STACK ( size -- ) ( Data only accessed by DOES> code )
CREATE ( GAWD I AM AN IDIOT. )
> 0 , DUP , 2* ALLOT ( Object holds # of elements in stack, )
> ( Total # possible, and a hunk o space )
> DOES> ( command# -- ?varies? )
> SWAP R>
> R@ PUSH>STACK = IF ( If we wish to add to the stack... )
> DUP DUP 2+ @ SWAP @ > IF ( If there's room )
>
[remainder deleted]
.
.
.
Sorry for any confusion that may have caused. I did say I was rusty.
.
. -Caj
[signature deleted tooo] -z91...@mp.cs.niu.edu
It sounds great for me. Actually my OO-Forth looks very much like a low level
OO language (if you like the term an OOP assembly) to me.
(I am planning to publish the details in FD.)
Andras
> What do you think of this method for vectored execution, and is it "ANSI" ?
Of course NOT!
Andras
AUGH! I have seen zero instances of examples that show how this
is done. Someone please post code that shows how CREATE DOES> can
even be remotely considered OOP. Real code with multiple methods
and multiple objects, no need for inheritance.
--
Darin Johnson
> You make a mistake here! FOR does not store to the variable itself, but to
> the place the execution token of the variable points to.
> Perhaps you try
> : FOR ' EXECUTE ! ; ( I'm not sure wether >BODY will be ok, too? )
> : EDIT (EDIT) @ EXECUTE ;
Thanks. I see what I did wrong now. That's what I get for not having a
copy of any Forth books on hand (that situation has been partially
remidied with the public domain texts on forth). I'll change the
definitions and see if that helps.
Without inheritance it must be very *remotely*.
Andras
AUGH! I have seen zero instances of examples that show how this
is done. Someone please post code that shows how CREATE DOES> can
even be remotely considered OOP. Real code with multiple methods
and multiple objects, no need for inheritance.
Merry Christmas.
--
Raul D. Miller N=:((*/pq)&|)@ NB. public e, y, n=:*/pq
<rock...@nova.umd.edu> P=:*N/@:# NB. */-.,e e.&factors t=:*/<:pq
1=t|e*d NB. (,-:<:)pq is four large primes, e medium
x-:d P,:y=:e P,:x NB. (d P,:y)-:D P*:N^:(i.#D)y [. D=:|.@#.d
\ Raul Miller, Sun Dec 25 07:27:52 EST 1994
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ Forth object example
\
\ symbolic piles of blocks
\
\ any block is a member of a "pile"
\ two piles may be "piled" together becoming a single pile
\ any block may be painted individually
: bump ( ref -- newval )
dup @ cell+ over ! @ ;
: method:: create 0 , does> bump constant ;
method:: method:
method: .display- \ display- anyobject
method: pile- \ pile- topobject bottomobject
method: piling- \ (used by pile-)
method: paint- \ paint- paint block
method: end-of-methods \ psuedo method used in class definitions
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ object structure
\ class:: <class:> creates an class identifier, and leaves a
\ reference to the class method structure on the
\ stack.
\ method- with routine identifies routine as the handler for the
\ named method of the class identified on the
\ stack. There's a special method, 0 which is
\ used during object creation.
\ <class:> <name> creates an object.
\
\ objects use the generic syntax: method- <name>
\ any messages required for a method must already be on the stack
\
\ each objectref has classref as first cell
\ methods are offsets into a class
: dispatch ( method objref -- objref ) ( ? objref - ?? )
tuck @ + @ execute ;
: class:: ( -- classref ) \ ( -- objref ) ( ? objref - ?? ) \ see above
create here end-of-methods allot does>
create here over , swap @ execute does>
dispatch ;
: with ( classref method -- classref )
over + ' swap ! ;
: class; ( classref -- ) drop ;
: usemethod ( ? objectref method -- ?? ) swap dispatch ;
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ Paint
: makepaint" ( paintref -- )
drop postpone c" , ;
: paintpaint paint- ; ( paintref -- paintref paintmethod )
: .displaypaint ( paintref -- ) cell+ @ count type cr ;
\ ideally, I'd use the name-grabbing mechanism demonstrated on
\ comp.lang.forth, but I forget the details...
class:: paint:"
0 with makepaint"
.display- with .displaypaint
paint- with paintpaint
class;
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ Block
paint:" Wood Wood"
: makeblock ( blockref -- )
( self ) drop
( paint ) paint- Wood drop ,
( top ) 0 ,
( bottom ) 0 , ;
\ accessors
: block's_paint cell+ ; ( blockref -- block's_paint_ref )
: block's_top [ 2 cells ] literal + ; ( blockref -- block's_top_ref )
: block's_bottom [ 3 cells ] literal + ; ( blockref -- block's_bottom_ref )
\ traversal
: topblock ( blockref -- topblockref )
begin dup block's_top @ while block's_top @ repeat ;
: bottomblock ( blockref -- bottomblockref )
begin dup block's_bottom @ while block's_bottom @ repeat ;
\ class handlers
: .displayblocks ( blockref -- )
dup topblock
begin
2dup = if ." -> " else 3 spaces then
dup block's_paint @ .display- usemethod
dup block's_bottom @
while
block's_bottom @
repeat
2drop cr ;
: pileblock ( blockref -- bottomref bottombottom pilingmethod )
bottomblock dup block's_bottom piling- ;
: pilingblock ( pile_to_place_on_top place_for_this_pile blockref -- )
topblock
dup block's_top >r
swap ! \ this pile under top pile
r> ! ; \ top pile above this pile
: paintblock ( paintref blockref -- )
block's_paint ! ;
class:: block:
0 with makeblock
.display- with .displayblocks
pile- with pileblock
piling- with pilingblock
paint- with paintblock
class;
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ Example usage
paint:" Red Red"
paint:" Yellow Yellow"
paint:" Blue Blue"
block: A
block: B
block: C
block: D
block: E
.display- B
paint- Red B
paint- Yellow C
paint- Blue E
.display- B
pile- A B
.display- B
pile- D E
pile- A D
.display- B
RDM> AUGH! I have seen zero instances of examples that show
RDM> how this is done. Someone please post code that shows
RDM> how CREATE DOES> can even be remotely considered OOP.
RDM> Real code with multiple methods and multiple objects, no
RDM> need for inheritance.
Thanks for your example at the end of your mail.
The following is on a more primitive level. CREATE.. DOES> should be
considered OOP here, I think. Choice among methods, binding, is done
without naming classes, only by a counting vector.
I did a similar thing in different environments as well, so for indexing
data files - sorting and file-i/o are methods, switched to the behaviour
as desired at runtime.
Convert digits to numbers, 1, 2, 3, 4 cells width. Provide number
conversion dependant on a 'width'-operator. Stuff to calculate should
be given already ('>QNUMBER', '>TNUMBER'), as well as auxiliary things:
'PUNCT?' checks if
ascii code is punctuation, 'NUM-CLASS' checks for leading '-' or '$',
'&', '%', sets variable BASE accordingly, and gives a flag for 'negative
value'.
: MN-EXE create
DOES> swap 1- 0 max cells + @ execute ;
' >qnumber
' >tnumber
' >number
:noname 0 rot rot >number rot drop ;
mn-exe >MNUMBER , , , ,
:noname 0. 2swap 0. 2swap ;
:noname 0. 2swap 0 rot rot ;
:noname 0. 2swap ;
:noname 0 rot rot ;
mn-exe MNUMZERO , , , ,
:noname 2drop 2drop ;
:noname 2drop drop ;
:noname 2drop ;
:noname drop ;
mn-exe MNUM-OFF , , , ,
: TO-MNUMBER ( a n width -- [data] dpl -1 // 0)
rot rot
over >R 2dup + >R
rot dup >R mnumzero
begin R@ >mnumber
over c@ punct? over and
while over R> swap R> drop
R> 1+ >R >R
>R 1 /string
repeat R> rot rot
over R> - 1-
rot R> = 0= rot 0= and 0=
if drop mnum-off 0 exit
then nip -1 ;
: MNUMBER? ( a n width -- [data] dpl neg? -1 // 0)
over 0= if drop nip exit then
base @ >R >R
num-class R> swap >R
to-mnumber R> swap R> base !
dup 0= if nip then ;
Ewald
Ewald Pfau:
[5] Thanks for your example at the end of your mail.
....................... end of quoted material .......................
Line [1] is from Ewald's post and announces mine
Line [2] is from my post and announces Darin's
Line [3] is from somebody that Darin was quoting (I think J. Fox)
who was not identified in Darin's post
Line [4] is by Darin
Line [5] uses the word "your". The example was provided by me, but
the text he was quoting was from Darin. I presume this is my fault
for placing Darin's name in front of text written by somebody else.
Sorry about that...
RDM> Line [1] is from Ewald's post and announces mine
RDM> Line [2] is from my post and announces Darin's
RDM> Line [3] is from somebody that Darin was quoting (I think J.
RDM> Fox) who was not identified in Darin's post
RDM> Line [4] is by Darin
RDM>
RDM> Line [5] uses the word "your". The example was provided by
RDM> me, but the text he was quoting was from Darin. I presume
RDM> this is my fault for placing Darin's name in front of text
RDM> written by somebody else.
RDM> Sorry about that...
So sorry from my side as well, did not watch for who wrote what in the
original postings.
Ewald
>> In an OO assembler (I dont
>> think one exists, so Im working on it myself), the assembler would insert the
>> address of the right procedure for the object in the jump instruction,
>> thereby eliminating the detour through the 'completely general' procedure.
>
>> In an OO assembler (I dont
>> think one exists, so Im working on it myself), the assembler would insert the
>> address of the right procedure for the object in the jump instruction,
>> thereby eliminating the detour through the 'completely general' procedure.
>
>Huh? An OO compiler for a RISC (or CISC) can't do this when
>generating assembler code? OO doesn't belong at the assembler
>level unless you have a specific OO architecture in mind.
Name an OO architecture that doesn't. Actually, just name an OO
"architecture" for everyones benefit, so we can see how it relates to OO
programming.
>Plus, once you abandon the 'completely general' procedure, you
>abandon a lot of OO usefulness. What is the assembler going to
>do if it doesn't know the object at assembly time?
>
>And why is this discussion done at the assembler level instead
>of the compiler level?
Use a little imagination, Darin. The completely general procedure just
does the routing to the procedure appropriate for the particular object.
In an OO assembler, the assembler takes the place of the general
procedure by looking at the context. Refer back to the methodology I
introduced for message passing in assembly. Just using that, you can
have all the features of OO. The purpose of discussing this at assembly
level is that it's just as simple! Whats complicated about moving a few
addresses into a couple registers?
In fact the whole purpose of OOP is to overcome the shortcoming of high
level languages: a variable can't refer to a procedure in a very elegant
way. ie, you can't have jump tables in C.
Now, depending on the CPU, using jump tables in assembly can be hairy or
*sweet*, but it's generally doable without too much fuss.
You seem to be forgetting, compilers compile (most of them do, anyways)
to machine code, not assembly code. Assembly is as high level as you
want. It's similarity to FORTH is that it's extensible, via procs,
macros, equates, and so forth. You could extend an assembly language to
look like any high level language, except FORTH, where you would have to
change syntax, if writing on a stack machine. Assembly language isn't a
language where each instruction corresponds to one machine instruction,
it's a language where you have *absolute control* over every machine
instruction, if you wish, or dont see machine instructions at all, if you
use someone elses canned procedures, macros, etc.
Perhaps I misunderstood what you were trying to say here, but it's
certainly possible to have tables of addresses of functions in C, and
to branch to those functions "through" the table. The code generated
by the compiler for this is quite efficient.
If you want an example of an OOP assembly, look at the back of the
Smalltalk-80 book (The Language And Its Implementation) for the
description of it's byte code. It makes use of a relatively small
set of instructions that are oriented to OOP.
--
Darin Johnson
djoh...@ucsd.edu
"Particle Man, Particle Man, doing the things a particle can"
However, the typical compiler overhead for calling a C function can be
rather unpleasant in some contexts.
Well, 99% of OOP is automating that standard.
> The question is, just how do you set up a CREATE .. DOES>
> structure to handle multiple methods instead of just one? Well, it's not
> hard to come up with any number of clever ways to do this, but remember:
> it must be encapsulated to the point that users of your objects need not
> understand the inner structure of them in order to use them.
Good, an example at last.
But... OOP and abstract data types are not the same thing. What
you've got appears to just be an abstract data type.
> 1 CONST PUSH>STACK ( Constants refer to individual methods )
> 2 CONST POP>STACK
> 3 CONST TOP>STACK
This is ok, but you then must make sure that all classes agree
on method numbers!
What you seem to imply is that you have a "method>class" naming
structure. The trouble here is that you have 0 polymorphism, which
is very important. While it is useful to have "PUSH>STACK" and
"PUSH>FLOAT_STACK" be separate (you don't want to confuse the two),
it is less useful to have "PUSH>STACK" and "PUSH>QUEUE" have
different names.
Much of the advantage of OOP comes from not having to know the
type or class of the object you are operating on. Thus you can
substitute different classes with no effort. It's better to just
have names like "PUSH", "POP", and "TOP" instead. Assigning
constants as you do will only be practical if you have a small
number of pre-determined methods.
As far as your example, there's little there to show an advantage
to Forth over other languages. That's what the original article
that started this thread claimed. Doing the same stuff in C for
instance is just as straight forward, for instance:
bob = make_stack(37);
push_stack(bob, 3);
When you start getting to the high-end, with a more general
method dispatcher, inheritance, and so on, then Forth will start
giving advantages over C.
> Is that a fair example? I don't want to even think about
> how you'd do multiple inheritance and polymorphism. Yeeeeeeeeeee.
Well, forget multiple inheritance. How about single inheritance?
(although I didn't even ask for that in my original request)
--
Darin Johnson
djoh...@ucsd.edu
- I'm not a well adjusted person, but I play one on the net.
> Merry Christmas.
Ok, much better example than before. But two points. First is that
you're 99% of the way to full blown OOP. That is, it's hardly a
simple example. The original argument wasn't that Forth couldn't
be extended to be OOP. The argument was that it was *already* there.
That is, one can start coding up your piles classes without writing
a lot of support code. Thus, your example doesn't support the
original unfounded claim (that Forth compares well to Smalltalk
in the OO arena).
The second point is that it doesn't really show where CREATE DOES>
"provides much of what is thought of by most people as OOP".
It simplifies a few things here and there, but that's about it.
IMHO, CREATE DOES> is just a limited macro capability, because
having:
: FOO create 0 , does> x y z ;
FOO bar
is equivalent to having a macro that expands to:
variable <bar>
: bar <bar> x y z;
In your example, what's central to OOP (at least late-binding OOP),
is essentially "dispatch". What CREATE DOES> does for you is to
create code to call "dispatch" after pushing the objects address.
There's a lot of syntactic nicety here, especially over C, but
nothing inherent about CREATE DOES> that gives you OOP. Compare
to Lisp and show where Forth buys an advantage.
>> In an OO assembler (I dont
>> think one exists, so Im working on it myself), the assembler would insert the
>> address of the right procedure for the object in the jump instruction,
>> thereby eliminating the detour through the 'completely general' procedure.
[... Impossible ...]
Use a little imagination, Darin. The completely general procedure just
does the routing to the procedure appropriate for the particular object.
In an OO assembler, the assembler takes the place of the general
procedure by looking at the context.
Often the context isn't known till run-time (it isn't called
late-binding for nothing). In some cases, you might be able to work
out earlier, e.g. at link-time that only one method could be called
at a specific call-site, but this is particularly difficult if your
language is not statically typed ...
In fact the whole purpose of OOP is to overcome the shortcoming of high
level languages: a variable can't refer to a procedure in a very elegant
way. ie, you can't have jump tables in C.
Hmm, I never found 'variable = fn1; variable();', particularly inelegant.
What is lacking is the encapsulation of data with functions, such as in
OO objects or closures.
You seem to be forgetting, compilers compile (most of them do, anyways)
to machine code, not assembly code.
Most Unix C compilers generate assembly code and call the assembler.
Assembly is as high level as you want.
No it isn't, and can't be. What if I want a type checker, infix
expressions, a module system, etc ?
Assembly language isn't a
language where each instruction corresponds to one machine instruction,
it's a language where you have *absolute control* over every machine
instruction, if you wish, or dont see machine instructions at all, if you
use someone elses canned procedures, macros, etc.
If you don't see the instructions you have lost your control over the
machine instructions. Why are you using an assembler then ?
David Gay
dg...@di.epfl.ch
Ok, much better example than before. But two points. First is
that you're 99% of the way to full blown OOP. That is, it's hardly
a simple example.
What's a simple example of OOP?
The original argument wasn't that Forth couldn't be extended to be
OOP. The argument was that it was *already* there. That is, one
can start coding up your piles classes without writing a lot of
support code.
You can start coding without writing a lot of code? :-)
Seriously though, BUMP and DISPATCH were a part of an implementation
of polymorphism -- I don't think you mean that you can't write OO code
that's not polymorphic, do you?
Thus, your example doesn't support the original unfounded claim
(that Forth compares well to Smalltalk in the OO arena). The
second point is that it doesn't really show where CREATE DOES>
"provides much of what is thought of by most people as OOP".
I guess I'll need to come up with a simpler example then...
: counter:: create 0 , does> : ;
counter:: counter:
counter: count.read literal @ ;
counter: count.up literal dup dup @ 1+ swap ! @ ;
: updown:: create 0 , does> : ;
updown:: updown:
updown: updown.read literal @ ;
updown: updown.up literal dup dup @ 1+ swap ! @ ;
updown: updown.down literal dup dup @ 1- swap ! @ ;
This example should have none of the pesky featurism that seemed to
plauge my earlier example. Note also the existence of multiple
objects (counter and updown), and multiple methods for each object.
Note also the use of CREATE DOES> to define each object.
>In fact the whole purpose of OOP is to overcome the shortcoming of high
>level languages: a variable can't refer to a procedure in a very elegant
>way. ie, you can't have jump tables in C.
The real purpose of OOP is to save *typeing*, you only type in the OOP bits
once then reuse them. This avoids the 90% of errors caused by typing
mistakes. The other advantages are handy to have :-)
FORTH typifies what I think of a Object Based Programming, where objects
are explicitly passed around, and methods handling is fairly explicitly
coded. OOP on the otherhand (applied to compiled languages) is a way
of making the compiler do some of the typing and thinking for you, in a
fairly intelligent way.
>
>Now, depending on the CPU, using jump tables in assembly can be hairy or
>*sweet*, but it's generally doable without too much fuss.
>
Having recently worked on a C program that used jump tables, pointers to
functions (stored in the data structure using it) and plentiful switch
statements (coded as jump tables in most compilers) whats so hard about
data pointing to code in C?
>You seem to be forgetting, compilers compile (most of them do, anyways)
>to machine code, not assembly code.
All the compilers I've used compile to assembler source or have options
to do so! (GNU, Borland 2,3,4 and a few others)
>Assembly is as high level as you
>want. It's similarity to FORTH is that it's extensible, via procs,
>macros, equates, and so forth. You could extend an assembly language to
>look like any high level language, except FORTH, where you would have to
>change syntax, if writing on a stack machine. Assembly language isn't a
>language where each instruction corresponds to one machine instruction,
>it's a language where you have *absolute control* over every machine
>instruction, if you wish, or dont see machine instructions at all, if you
>use someone elses canned procedures, macros, etc.
Assembly language largely DOES equate 1 instruction=1 machine instruction.
(The exceptions generate no code). You appear to be talking about macro
assemblers, which effectively perform textual manipulation of the source
before assembling it. Assembler is extendible in a simple minded way.
Extend too far and you start to lose the advantage of tight control of the
code generated. Extend too far and the output is no longer optimised (and
its almost impossible to make an assembler do simple things like spot
duplicate instructions...)
For real OOP power you need strong database handling which no assembler I
know of can supply (weak handling yes...). Bare FORTH is not much better
but FORTH is extendible in a much more flexible, more complete way. More
important, there no practical limit to how far you extend
--
Paul Shirley: Coffee Hunter Extreme
: update ( addr val -- val ) dup rot ! ;
That doesn't what? Currently, I know of no OO architectures in
hardware, which supports my assertion that you don't need one
to do efficient OOP. Good OOP compilers for RISC exist without
the need for a fancy jump instruction. The original posting
seemed to imply that this was needed as if compilers weren't
smart enough to do this.
Anyway, the Smalltalk byte-code seems a good example of an
OO architecture. It's not in hardware though. SOAR is another,
thought I don't know if it ever made it to hardware or not.
SOAR basically supported better virtual memory, memory tagging,
and the like, as opposed to OO dispatching.
> In an OO assembler, the assembler takes the place of the general
> procedure by looking at the context.
Assembler, not the machine? Then why can't the compiler do it?
High level languages were invented to make programming simpler
and get away from assembly. Adding OOP to assembler isn't going
to make anyone go back. Much of OOP is syntactic anyway, something
unsuited to assembler.
> In fact the whole purpose of OOP is to overcome the shortcoming of high
> level languages: a variable can't refer to a procedure in a very elegant
> way. ie, you can't have jump tables in C.
No jump tables? What C book are you reading? A table of function
pointers works great - may be not as quick as in assembler but more
maintainable. GNU C allows arrays of labels, and that's the same
thing.
> You seem to be forgetting, compilers compile (most of them do, anyways)
> to machine code, not assembly code.
Most of them can do both. At least all I've ever used (unix, vms, amiga).
> Assembly is as high level as you want.
Ah, I see your hangup. Oh well. I can see the advantage in assembler
for some things, but if you can't see the advantage to a high level
language in anything, it's hopeless. But then, why are you reading
this group?
FYI, here are some off the cuff advantages to high level languages,
including Forth:
- portability. If you don't think this is important, you need to
see your optometrist. Maybe you personally don't need it (or
think you don't), but you're not the whole world. What happens
when you need to port to a new machine? What if you have to
use a new assembler that doesn't have all your nice macro
features?
- maintenance. Assembly is hard to maintain, difficult to use
for multi-person projects.
- simplicity. Assembly programmers worry about optimization
instead of allowing a compiler to help. Optimization is nice
sometimes, but even stuff that doesn't need much optimization
in assembly tends to be tweaked to the point of unreadability.
Let the compiler shuffle your registers and parse your
formulas for you (which was why Fortran was initially invented).
- high level features. A bigger namespace, memory management,
string operations, complex numbers. Automatic parallelization
and vectorization on supercomputers (then recode the critical
stuff in assembler later after things are working). Interpreters.
Code profilers and trace coverage. Symbolic debuggers. Type
checking. And so on.
--
Darin Johnson
djoh...@ucsd.edu
>> 1 CONST PUSH>STACK ( Constants refer to individual methods )
>> 2 CONST POP>STACK
>> 3 CONST TOP>STACK
>>
>> : STACK ( size -- ) ( Data only accessed by DOES> code )
>
> CREATE ( GAWD I AM AN IDIOT. )
>
>> 0 , DUP , 2* ALLOT ( Object holds # of elements in stack, )
>> ( Total # possible, and a hunk o space )
>> DOES> ( command# -- ?varies? )
>> SWAP R>
>> R@ PUSH>STACK = IF ( If we wish to add to the stack... )
>> DUP DUP 2+ @ SWAP @ > IF ( If there's room )
>>
> [remainder deleted]
> .
Hmm, how about;
: CELL- ( addr--addr) NEGATE CELL+ NEGATE ; \ every system should
: -ROT ( a b c--c a b) ROT ROT ; \ have these
: << :NONAME ; \ :NONAME is no name
: >> POSTPONE ; ; \ for a Forth word
: METHOD CONSTANT ; \ minimal message
: OBJECT DOES> SWAP EXECUTE ; \ passing words
<< DUP @ CELL+ TUCK SWAP ! ! >> METHOD PUSH ( n--)
<< DUP @ DUP @ -ROT CELL- SWAP ! >> METHOD POP ( --n)
: STACK ( n) CREATE OBJECT HERE , CELLS ALLOT ;
/ -- usage -- /
20 STACK FRED ok
10 PUSH FRED ok
11 PUSH FRED ok
POP FRED . 11 ok
POP FRED . 10 ok
BCNU, Gordon <gor...@charlton.demon.co.uk>
Please could you eMail any responses to this as well as posting to c.l.f as
some news is coming v. slow at the moment.
I'm not clear on the distinction between "syntactic nicety" and OOP.
You could argue that any OOP is just providing syntactic niceties.
Perhaps you could explain what you mean in a fashion that doesn't
apply to accepted OOP languages?
: counter:: create 0 , does> : ;
counter:: counter:
counter: count.read literal @ ;
counter: count.up literal dup dup @ 1+ swap ! @ ;
: updown:: create 0 , does> : ;
updown:: updown:
updown: updown.read literal @ ;
updown: updown.up literal dup dup @ 1+ swap ! @ ;
updown: updown.down literal dup dup @ 1- swap ! @ ;
--
I guess it's back to the old sticking point. I don't consider
that the capability of adding in OO extensions makes the original
unextended language OO. In your example, most of it was coding
in simple OOP capabilities. I, and no one else, ever claimed
Forth was incapable of doing this. Heck, you can do that in
assembler as well, but few people call that an OO language.
The original assertion was that CREATE DOES> was the basis of OOP.
In your example, the basis was dispatch and method creation.
CREATE DOES> was just syntactic nicety.
Apart from SOAR, which you mention later, there were several machines
made at Xerox PARC (the fastest was the Dorado), which supported
Smalltalk trough the architecture (but through microcode), and the
Rekursiv architecture.
|> Good OOP compilers for RISC exist without
|> the need for a fancy jump instruction. The original posting
|> seemed to imply that this was needed as if compilers weren't
|> smart enough to do this.
|>
|> Anyway, the Smalltalk byte-code seems a good example of an
|> OO architecture. It's not in hardware though. SOAR is another,
|> thought I don't know if it ever made it to hardware or not.
|> SOAR basically supported better virtual memory, memory tagging,
|> and the like, as opposed to OO dispatching.
I have the impression that SOAR has seen hardware. However, Ungar
notes in his Ph.D. thesis that the compiler improvements were more
important than the hardware ideas. Hardware manmufacturers seem to
have concluded the same , since they don't include special OO support
in their hardware.
- anton
--
M. Anton Ertl Some things have to be seen to be believed
an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
iAPX 432 ? :-)
The syntax looks nice and clean, and definately this is a
keeper for the "interesting program techniques" file.
But... It's not OOP. That's because "PUSH" will only
work for STACK's. That is, your methods are not really
any different from normal functions (ie, it's just as
easy to do "12 FRED PUSH" where PUSH is just a normal
colon word).
--
Darin Johnson
djoh...@ucsd.edu
"Here was a man who knew what to do with 2000 pounds of ammonium
nitrate, fuel oil, a 64 K-processor CM5 and a few blasting caps."
OOP should be doing a lot at either compile time or run time
(the latter for Forth is by far the simplest). That's where
your DISPATCH helps. Your CREATE DOES> is a syntactic nicety
since what it basically does is just save a bit of typing
(ie, you can do "method object" instead of "method object dispatch".
CREATE DOES> just binds a single procedure to some data (plus
initialization). That's not OOP. It does nothing more than
a macro could, no matter how much Forth aficionados claim that
this is the eigth wonder of programming language features.
However, the procedure that is bound can make the difference,
and binding DISPATCH is what does the basic OOP.
--
Darin Johnson
djoh...@ucsd.edu
Caution! Under no circumstances confuse the mesh with the
interleave operator, except under confusing circumstances!
A bigger reason probably is that it is just too expensive to do
new hardware designs anymore unless you're a giant company.
It's economically infeasable to try to come out with new hardware
that had support for non-conventional ideas. Lisp or Smalltalk
machines could not be built today, except perhaps by upgrading
old designs.
Likewise a Forth machine may never make it out of the research
labs or universities, at least not enough to get noticed except
in niche markets. So you get a great Forth-on-a-chip - how can
that compete when you can get existing hardware for a fraction
of the cost? (if it's slower then spend more money and get a faster
one or add more memory, it's still cheaper)
--
Darin Johnson
djoh...@ucsd.edu
The opinions expressed are not necessarily those of the
Frobozz Magic Hacking Company, or any other Frobozz affiliates.
No one keeps you from OOP'ing with macros (only perhaps some human
wording parsers) :-)
You may even evaluate expressions having different meanings in different
wordlists. So the wordlist switching is the act of binding. This is
funny: as more as human language is stressed to be meaningful in one
dimension only (in the technical view upon things, but as well in
merchandizing and even in entertainment - such aspects claiming more and
more to be the only ones), so more some crazy machinery is the nicer a
pet if being capable of well-formed ambiguity...
In dealing with Forth, I had to state the difference somewhere. It reads
like this:
"Often in use [in Forth] is a property (which no other compiler has this
way), which enables to couple runtime behaviours to data structures, by
inheritance - in terminology of object oriented programming this means:
data objects may be associated to single methods; should this be
diversified into classes, so an extension would be necessary which,
depending on requirements, would turn to be rather compact. Since the
principle of inheritance is given all along, so the need to recurse on
class bindings of methods should be regarded as far less urgent than for
compilers, which only come as readymade platforms (that is, an essential
feature of OO-programming is in use in Forth since all the time)"
Happy New Year!
Ewald
(since I translated the above paragraph, here is the German version;
perhaps I am not that good in translating...:)
Haeufig Gebrauch gemacht wird zudem von der Eigenschaft (die andere
Compiler so nicht haben), dass Laufzeiteigenschaften per Vererbung an
Datenstrukturen gekoppelt werden koennen - in der Terminologie des
Object Oriented Programming: an einzelne Methoden lassen sich Objekte
assoziieren; sollte dies nach Klassen aufgeschluesselt werden, so waere
eine Erweiterung noetig, die aber dank der gegebenen Moeglichkeiten je
nach Bedarf recht kompakt ausfallen kann. Indem das Prinzip der
Verbbarkeit in Forth immer schon gegeben ist, kann der Bedarf dafuer,
auf Klassenbindungen von Methoden zurueckzugreifen, als wohl weit
weniger gravierend eingeschaetzt werden, als wenn ein Compiler per
Definition nur mit vorgefertigten Geruesten aufwarten kann (d.h. ein
wesentlicher Teilaspekt des OO-Programmierens ist in Forth immer schon
in Uebung).
Heiko Wengler
PS: That's from the numerous papers by Unger about Self.
>But... It's not OOP. That's because "PUSH" will only
>work for STACK's. That is, your methods are not really
>any different from normal functions (ie, it's just as
>easy to do "12 FRED PUSH" where PUSH is just a normal
>colon word).
Sure it's not OOP (what is?, these days I'm not even sure what Forth is),
but I never claimed it was. In fact in terms of functionality it is
identical to Caj's posting. I posted it because it's a trick I've used on
occasion to good effect and I thought it may be of interest.
But since you rattled my cage you get to hear my opinion as an added bonus
(?)
No, Forth ain't OOP, Forth is Forth. It would make as much sense to claim
that Forth is functional, as many of the operators show referential
transparency and you can beef it up to be more like a functional language.
The first step is to add a variable width stack for larger data items (I've
done that bit), then list processing (is this a requirement of a functional
language, most of them have it but I think that is by the by) and then lazy
evaluation (again questionable?).
Lazy evaluation is the tricky one, I've been thinking about it on and off
for a year but come to no earth shattering revelations - probably switching
to postfix controlflow would help though. Has anyone followed this line of
thought through to a conclusion?
BCNU, Gordon <gor...@charlton.demon.co.uk>
/---------------------------------------------------------\
| Learn Forth in five minutes on the WWW |
| http://taygeta.oc.nps.navy.mil/forth_intro/stackflo.htm |
| (looks best with netscape) |
\---------------------------------------------------------/
Darin Johnson:
: OOP should be doing a lot at either compile time or run time (the
: latter for Forth is by far the simplest).
Um... in general, CREATE DOES> meets this criteria.
It works like this: CREATE <compile-time-code> DOES> <run-time-code> ;
: That's where your DISPATCH helps. Your CREATE DOES> is a syntactic
: nicety since what it basically does is just save a bit of typing
: (ie, you can do "method object" instead of "method object
: dispatch".
CREATE .. DOES> ... ; is a wee bit more than a syntactic nicety. If
you disagree, show me how to write a mix of compile time and run time
code under some other generic language (admissible: assembly, C, C++,
Fortran, COBOL, Pascal -- if you can't do simply it in any of those
languages it sure ain't just a syntactic nicety).
: CREATE DOES> just binds a single procedure to some data (plus
: initialization). That's not OOP.
Sure it is, if that single procedure is for use at compile time, and
if that data is thus available to a variety of methods.
: It does nothing more than a macro could, no matter how much Forth
: aficionados claim that this is the eigth wonder of programming
: language features.
What kind of macros you talking about? I sure hope you don't believe
that cpp can do everything that create does> can do.
: However, the procedure that is bound can make the difference, and
: binding DISPATCH is what does the basic OOP.
Obviously, the code you use makes a big difference. However, I find
it hard to believe that you think dispatch is the only way of doing
OOP -- first off, it's just an >>example<< of how to do polymorphism.
There's lots of other ways to do polymorphism, and there's lots of OOP
that's not polymorphic.
Here's a very simple example of OOP that uses CREATE> DOES which
doesn't use dispatch, and which isn't polymorphic. [Yes, I've posted
this code twice before. For some reason, you've completely ignored it
-- as best I can figure you've just plain not seen it?]
> In article <DJOHNSON.94...@arnold.ucsd.edu>,
> djoh...@arnold.ucsd.edu (Darin Johnson) wrote:
>
> >But... It's not OOP. That's because "PUSH" will only
> >work for STACK's. That is, your methods are not really
> >any different from normal functions (ie, it's just as
> >easy to do "12 FRED PUSH" where PUSH is just a normal
> >colon word).
>
> Sure it's not OOP (what is?, these days I'm not even sure what Forth is),
[le 'chomp']
> No, Forth ain't OOP, Forth is Forth. It would make as much sense to claim
Um, just what does everyone want to see?? My example wasn't supposed to
be true OOP - just multiple methods. If you want to see inheritance, give
me a day or two. In the mean time, perhaps we could streamline our thread
by defining EXACTLY what features we must provide in order for Forth to be
considered OOP, rather than just pointing at our examples and saying, "NO,
that's not it."
Can anyone even DEFINE object-oriented programming in 50 words or less?
I personally think it's an NP-hard problem. I tell you what: as soon as
I post this, I'll go home, dig up my copy of Grady Booch, and try to sift
out a suitable list of requirements, and how they may be implemented in
Forth. I'm pretty sure that book contains a specific list of requirements
somewhere amid the "paradigm"s and "aggregation"s (actually, that Booch
provides specifics about anything is a small miracle).
Until tomorrow then, Forth D00Dz.
-- __ +--------------------+------------------------+
,ad8888ba, (88)| Today's likes: | Today's dislikes: |
d8"' -- `"8b `""'| | |
d8' "A Neo- | 32 GPRs & 32 FPRs! | Working in Decimal |
88 NEO-Retro- ,adPPYYba, :88 | The Wonder Stuff | People that read |
88 Techno- "" `Y8 :88 | Putting off buying | self-referential .sigs |
Y8, Fest!" ,adPPPPP88 :88 | Christmas presents | without realizing it |
Y8a. -- .a8P 88, ,88 :88 +--------------------+------------------------+
`"Y8888Y"' `"8bbdP"Y8 :88 | It could have been worse - |
;88 | The media could have called it |
o=|z91...@mp.cs.niu.edu|88P; | the "Information Burger-King" |
http://I=still=hate=my=page' +---------------------------------------------+
Hmm, you listed only generally compiled languages. The simplest
example would have been in Lisp.
The trouble is, CREATE DOES> is most useful only in an interpreted
language. For instance, the most common use of it is as:
: FOO CREATE allocate-more-space DOES> run-time ;
However, in something like C, you can do:
struct word {
funcpointer cfa;
void *storage;
};
...
cfa = my_runtime_function;
storage = malloc(blah);
(or even static initialization if you want)
Plus, if you're allowed to use the C preprocessor, then you
can easily to run-time and compile-time together. For instance,
GNU Emacs code uses something similar to:
#define DEFUN(lname, fname, sname, minargs, maxargs, prompt, doc) \
Lisp_Object fnname (); \
struct Lisp_Subr sname = {fnname, minargs, maxargs, lname, prompt, 0}; \
Lisp_Object fnname
> : It does nothing more than a macro could, no matter how much Forth
> : aficionados claim that this is the eigth wonder of programming
> : language features.
>
> What kind of macros you talking about? I sure hope you don't believe
> that cpp can do everything that create does> can do.
Lisp macros. In fact something extremely close to CREATE DOES> could
be done quickly. Except that doing so isn't as useful as it is in
Forth.
> Here's a very simple example of OOP that uses CREATE> DOES which
> doesn't use dispatch, and which isn't polymorphic. [Yes, I've posted
> this code twice before. For some reason, you've completely ignored it
> -- as best I can figure you've just plain not seen it?]
>
> : counter:: create 0 , does> : ;
> counter:: counter:
> counter: count.read literal @ ;
> counter: count.up literal dup dup @ 1+ swap ! @ ;
>
> : updown:: create 0 , does> : ;
> updown:: updown:
> updown: updown.read literal @ ;
> updown: updown.up literal dup dup @ 1+ swap ! @ ;
> updown: updown.down literal dup dup @ 1- swap ! @ ;
Hmm, doesn't compile very well in PFE... But I'll make assumptions
on what it's supposed to do.
I probably didn't pay attention to it because it doesn't look
very OOP. That is, you have to redefine the "methods" for each
object instantiation. Ie, no inheritance or cloning or prototypes.
It doesn't match any definition of OO I've seen anywhere outside
this group.
It's the same as doing:
variable counter 0 counter !
: count.read counter @ ;
: count.up counter dup dup @ 1+ swap ! @ ;
etc.
or
variable counter 0 counter !
counter : count.read literal @ ;
counter : count.up literal dup dup @ 1+ swap ! @ ;
Except some typing was saved your way in the long run.
As much as you argued that CREATE DOES> is nothing like a macro,
your code can be done easily as a macro in other languages, since
text substitution is really all that is needed. Hmm, I can't
even think of a reason to do the above in C though, since it's
just multiple routines accessing the same global variable...
--
Darin Johnson
djoh...@ucsd.edu
"I wonder what's keeping Guybrush?"
Is the point being missed again? No one ever claimed Forth couldn't
be made to be OOP by spending time to add onto it. It can do that,
and do it better than most languages because it can end up with a nice
syntax as well when done.
What was claimed was that Forth was OOP *already*, no need to spend
a day or two on it, or to load in an OOP package, or whatever. The
claim was that it was already there (the other claim was that CREATE
DOES> was the component that made it OOP).
> Can anyone even DEFINE object-oriented programming in 50 words or less?
> I personally think it's an NP-hard problem.
Actually, it used to be straight forward, until every new language and
vendor wanted to be called OO and gave their own definition so they
would match.
But no need to get a definition. For any you can get, Forth can be
*extended* to match that definition. Heck, Forth can be "extended"
to accept smalltalk as input if you want to put the effort into it
(the question being is if a Forth thus extended can be called Forth,
whereas a Smalltalk implemented in assembler is no longer considered
assembler :-)
But what is it about Forth *right*now* without extending it that
makes it OOP? I haven't seen any definition for OO that ANS Forth
matches out of the box.
--
Darin Johnson
djoh...@ucsd.edu
The full name of the compiler is "Compiler Language With No Pronounceable
Acronym", which is, for obvious reasons, abbreviated "INTERCAL".
Definition? Hmmm.
But it must have:
- Encapsulation (CREATE DOES> is OK).
- Inheritance.
- Late (dinamic) binding!!!!!
- Polimorphism.
I think the latter two is definitly NOT supported by CREATE DOES>.
Andras
Actually that's a good "basic" definition but I would modify it
to be a little more generic:
- Encapsulation (CREATE DOES> is OK)
- Inheritance
- Polymorphism
- A binding strategy:
+ Early, ie. static
+ Late, ie. dynamic
- A typing strategy:
+ Early, ie. compile time (we see this strategy in C++)
+ Late, ie. run time (allows information about the
object's type/class to be determined at run time, we
see this strategy in Objective-C; typically used with
a late binding strategy)
Additions to the "basic" OO definition, but not required to be
considered OO, are:
- A strategy to combine unrelated classes
+ multiple inheritance, ie. Smalltalk like
+ protocols, ie. Objective-C like
- Multiple root classes
- Operator overloading
So... How about using the above "basic" OO definition as a
criteria to determine whether the various FORTH OO extensions
we have see are OO. For the more ambitious they can present
some of the "additional" OO features.
I forget who said that this discussion got off track a little
since from what I have seen, most agree that FORTH and C both
allow one to extend the language to have OO features. Lets
not redebate that, but lets see some FORTH implementations of
the "basic" OO criteria and analyze their strengths and
weaknesses.
--
Andrew P. Houghton, MC 265 Internet: a...@oclc.org
OCLC Online Computer Library Center, Inc.
6565 Franz Road
Dublin, Ohio USA 43017-0702 NeXT Mail accepted.
My original assertion that CREATE DOES> provides the basis or OOP
has been demonstrated many times by many people in many ways now.
It appears to me now that this thread is really going in circles.
When I said that that CREATE DOES> provides the basis of OOP I
was not saying "CREATE DOES>" as a 12 character string out of
context. Sure CREATE DOES> by itself does not give you everything
in your list of requirements. It only creates a work called DOES> :-)
I WAS talking about using CREATE DOES> with a little more code !
The examples I have seen have been very small and certainly back the
assertion that CREATE DOES> provides a basis for OOP.
Ok if the OOP system ends up using 50 megabytes on my hard disk then
I will agree that it is not a normal use of CREATE DOES> with a
little Forth code.
It seems that almost everyone agrees that you can extend Forth
or C to become an object oriented platform. However it STILL
appears to me that in Forth it is little more than the standard
use of a facilty that has been in the language for a long time.
i.e. CREATE DOES>
Jeff Fox
{ quite a bit of stuff about 50 words or less defining OOP }
: OOP pointless unnecesary bad ; ( this is the cynical/humorous one)
a system of programming which treats data as a virtual "physical
object", about which things may be observed or changed.
explanation is longer than 50 words, tho....
data is like a 3space solid. you can change its color on each face,
change the dimensions, rotate it, etc....
basically just like chunking data together.
envision a filing cabinet..... you can manipulate the entire thing
(with a hand truck), a drawer, a section of folders, a folder, or one
piece of paper in the folder.
sounds like pretty much pointless to me. just define what amounts to a
pascal RECORD and use that. (i am being shortsighted and not trying to
figure out any legitimate use for anything further)
--- email ... uwvax!gorgon!ruth!spqr , the domain path doesn't work.
OBNeatQuote: "My advice to you is to become rich." -- Josh Goldfoot
>- A strategy to combine unrelated classes
> + multiple inheritance, ie. Smalltalk like
> + protocols, ie. Objective-C like
I'm considering using variant classes, but first I need to implement an
object stack. BTW, it's been a while since I used Objective-C-- where
can I learn about 'protocols'?
>- Multiple root classes
Easy to do-- but why?
>- Operator overloading
Yes, that would be handy... although you'd have to build it yourself. So
my system dosen't provide that, so sue me. :) (No-- just kidding, I
didn't mean that!)
>I forget who said that this discussion got off track a little
>since from what I have seen, most agree that FORTH and C both
>allow one to extend the language to have OO features. Lets
>not redebate that, but lets see some FORTH implementations of
>the "basic" OO criteria and analyze their strengths and
>weaknesses.
OK, I'd like to see the standard version of OBJECTS.TXT; I'll post the
F-PC version here, with the assembler removed. I've changed a lot of the
factoring to support my extentions for it (to provide named, inheritable
member variables). Code follows: (I'll insert my guesses as to proper
ANS syntax, but I'd LOVE to see accurate ANS code)... If the outcome of
this is nice, I'll consider offering my member variable extensions for
improvement, unless I hear an objection.
\ OBJECT.SEQ From Forth Dimmensions, Volume 10, number 2
\ by Rick Hoselton
comment:
Some object oriented words slightly modified by Tom Zimmer
for use in F-PC.
Also by Billy, for the addition of member variables. These made the
tables below unnecesary, but I'm posting them just to help somewhat.
OFFSET #BYTES METHOD format
0 2 next older borther METHOD pointer
2 2 MESSAGE number
4 n METHOD's code
OFFSET #BYTES OBJECT format
0 2 father OBJECT address
2 2 youngest son OBJECT address + 4
4 2 next older brother OBJECT address + 4
6 2 youngest METHOD address
8 n optional local data
comment;
only forth also definitions
anew objectstuff
\ DEFINED? IF FORGET THEN CREATE (you get the idea...)
: action ( obj msg --- )
swap 6 +
begin @ 2dup 2+ @ =
until 4 + nip ( execute) ;
\ Action is a _noun_. It returns the action, not executes it.
\ It provides for polymorphism.
variable 'msg
variable 'object
\ This needs to be changed to a stack, but it work for some
\ purposes now.
: act ( pfa msg --- )
2dup 'msg @ ! 'object !
action execute ;
\ This is the verb, hence the execution belongs here.
: me ( --- ?? )
'object @ ;
: >object ( rel-addr --- addr )
me + ;
: >super ( rel-addr --- addr )
me @ + ;
: link, ( addr --- )
here over @ , swap ! ;
\ Can someone come up with a better word than this? I'd
\ rather have a clear word. This actually does what it says--
\ commas a link to the address, and is used a lot.
: object> ( --- )
'object link,
0 ,
2 >super link,
6 >super @ , ;
create master
master 'object !
object>
2 >object 6 erase
: (method) ( --- msg )
create here does> act ;
: ?create ( --- msg )
>in @ defined
if nip >body
else drop >in ! (method)
then ;
: (method:) ( --- )
?create
6 >object link, ,
\ Ugh! Yuck! Bleagh!
\ This simply compiles a definition without a header.
\ Hmm, sounds like :NONAME . Would that work?
,JUMP
>NEST HERE - HERE 2- ! \ link into JUMP the addr of nest
XHERE PARAGRAPH +
DUP XDPSEG !
XSEG @ - ,
XDP OFF
!csp ]
\ END Ugh! Yuck! Bleagh! segment
;
(method:) anchor ." I don't understand" ;
' anchor >body 2+ 'msg !
(method:) method: ( --- )
(method:) ;
master method: object: ( --- )
create object> ;
\S END of file
I'm not including the method management part, since that requires .ID.
Nope, late binding isn't a requirement. Simula is generally regarded
as the first OO language and it was early binding.
Encapsulation is just a matter of separating object from actions
on the object, you don't need anything special to do that. But
it's required IMHO for an OOP.
Inheritance can be let off somewhat, since you can do OO programming
without it (ie, programming by having an interaction of objects
and actions on those objects). It's just limited without it.
Polymorphism however is important. This basically means you can
send the same message to many different objects. Like function
and operator overloading. You can do "object print" instead of
having to do "mylist print.list" and "myarray print.array".
But I don't know if this is absolutely necessary.
In general, what's important is how the program is written, not
what features are there for it. An OOP system is one that makes
writing these OO programs easier. Since most OO programs use a
subset of the above features, providing language support for them
what makes gives a language an OO property.
--
Darin Johnson
djoh...@ucsd.edu
"You used to be big."
"I am big. It's the pictures that got small."
>What was claimed was that Forth was OOP *already*[1], no need to spend
>a day or two on it, or to load in an OOP package, or whatever. The
>claim was that it was already there (the other claim was that CREATE
>DOES> was the component that made it OOP).
I don't think I heard the first claim(1). I think that would be a little
overblown, since most OO packages for Forth that I've seen take at least
two screens of code. Nonetheless, Forth supports OO better than any
other language, including OO ones, since Forth is communicative while
they are notational. In other words, the primary purpose of Forth is to
communicate with the computer, while the primary purpose of most other
languages is to provide notation for you to read and write.
One side effect of this is that the notation in Forth is not fixed, as it
is in C, Ada and even Scheme (Scheme is the closest of these to a
communicative language, though). You can communicate any OO concept to
your computer (not possible in any notational language) using any
notation (obviously not possible in any notational language).
>> Can anyone even DEFINE object-oriented programming in 50 words or less?
>> I personally think it's an NP-hard problem.
Isn't that NP-complete?? At any rate, NP doesn't apply to this, since
it's a definition, not a solution.
>But what is it about Forth *right*now* without extending it that
>makes it OOP? I haven't seen any definition for OO that ANS Forth
>matches out of the box.
It can be used for OO right out of the box. Admitted, out of the box its
OO _flexibility_ is low, but that can be fixed by adding one
communication word and some additional notation. Perhaps I'll post
those. I don't have them in ANS Forth, though I'm translating them
(should be VERY short).
-Billy
>Definition? Hmmm.
>But it must have:
>- Encapsulation (CREATE DOES> is OK).
Well, my implementation actually gives some of that up-- the data members
are not hidden, unless you build them yourself.
>- Inheritance.
Yup.
>- Late (dinamic) binding!!!!!
That's the sort I use.
>- Polimorphism.
Yup, got it.
>I think the latter two is definitly NOT supported by CREATE DOES>.
They are supported by it; OO would take many times longer to build
otherwise. They are not, however, provided by it. Good thing, too, or
you wouldn't have a choice of which pm pethod to use.
>Andras
-Billy
New hardware designs are done all the time, and not always by giant
companies, but usually for existing architectures. That is so because
there is a cost for changing to a new architecture (new tools,
applications have to be ported) and they do not want to incur it
unless it offers a significant speed advantage. If there is a
significant speed advantage, however, they are willing to make the
change (e.g., VAX->Alpha, 68k->SPARC, 68k->HPPA, 68k->PPC).
Lisp machines were not a new design. They had an established
architecture with lots of software tools and applications for it
etc. But they could not keep up speedwise with RISC chips despite
their architectural support for the programming language. This is just
the same thing that happened to the VAX and the 68k architectures and
will happen to the 386 architecture and maybe even the IBM 360
architecture (if the customers of these machines ever care for CPU
speed).
OO support could be added to existing architectures, just like they
have extended the architectures to 64 bits in the last few years, but
it is not done inspite of the increasing popularity of C++. Looks to
me like it is not worthwhile speedwise.