[comp.lang.forth] Object oriented programming extension for forth.

mip@IDA.LiU.SE (Mikael Patel) (08/22/90)

Lately a number of postings have been on the subject of object
oriented programming extensions for forth. I have been working
on an extension (actually three models) and wish to distribute
and share the definition of one for discussion. In this posting 
I will only present the class-instance model (because of space). 
The other models, relations and prototypes, are more general and
actually used to implement the presented model. The source code
for all these models are available in the coming release of
TILE forth (version 3.33, release 2.1). 

The below included files are the manual pages for the OOP
extension and the test/example file. 

The syntax and notation is as close to Smalltalk-80 as possible.
Messages are defined and used as functions (a normal colon definition).
A message always requires an instance on top of stack. It is with 
the class information from the instance late binding is performed. 

A class is defined with internal fields (much like a structure) 
and methods for messages. The definition of a class also requires
a super class (which may be nil for a root class). To call the
super class realization of a message in a method the message prefix 
word "super" is used. The overall syntax (in EBNF) is:

<superclass> subclass <name>

{ <instance variable fields> }

{  method <message> ( ... self -- ...) ... <method definition> ... ; }

subclass.end

An instance is created in the following style:

<initiate parameters> <class> instance <name> ( -- object)

or

<initiate parameters> <class> new-instance ( -- object)

As shown the instance can be "bound" or "free". The message 
"initiate" is always passed to the newly created instance to 
perform initialization

Some of the latest postings have suggested using a prefix
message-passing operator. I have here viewed the message as 
a "normal" forth word. It will at run-time locate the appropriate
method using information from the class structure (or internal
information) and apply the method. A typical example of this
style of message passing is:

message initiate ( ... self -- )
message moveTo ( x y self -- )
...
 10 10 Point instance aPoint 
...
-10 10 aPoint moveTo

The style follows "normal" forth and there is, in principle, 
no difference between a colon definition and a message on
the "surface".

The below example file shows an object root class, a point
class, and the classical account example. Also a proxy class
is shown in the form of a traceable class. The error message
"doesNotUnderstand" is here defined as a method which passes
on the message to the actual object. This way of redefining
the error message may also be used to implement multiple
inheritance.

I believe that we should look for the definition of a common
object oriented extension for forth and then work on the real 
problem: A library with reusable classes. 

The below definitions are only a small step on this road. The
next step is yours.


Mikael R.K. Patel
Researcher and Lecturer
Computer Aided Design Laboratory (CADLAB)
Department of Computer and Information Science
Linkoping University, S-581 83  LINKOPING, SWEDEN

Phone: +46 13281821
Telex: 8155076 LIUIDA S			Telefax: +46 13142231
Internet: mip@ida.liu.se		UUCP: {uunet,mcsun,...}!liuida!mip
Bitnet: MIP@SELIUIDA			SUNET: LIUIDA::MIP


- - - - - - - - File: object.tst - - - - - - - - - - - - - - - - - 

.( Loading Objects test...) cr

#include objects.f83

objects string forth definitions


\ The set of messages needed for this example

message initiate ( self -- )

message isKindOf ( class self -- boolean)
message isMemberOf ( class self -- boolean)
message respondsTo ( message self -- boolean)

message instanceSize ( self -- num)
message copy ( self -- object)
message shallowCopy ( self -- object)
message deepCopy ( self -- object)

message doesNotUnderstand ( message self -- )
message subclassResponsibility ( self -- )
message shouldNotImplement ( self -- )

message perform ( message self -- )

message basicWrite ( self -- )
message write ( self -- )
message read ( self -- )

message where ( self -- x y)
message position ( x y self -- )

message balance ( self -- x)
message owner ( self -- x)
message deposit ( x self -- )
message withdraw ( x self -- )
message balance ( self -- x)


\ A class hierarchy with Object, Point, and Account

nil subclass Object ( -- )

method initiate ( self -- )
  basicWrite ." initiated" cr
;

method isKindOf ( class self -- bool)
  class
  begin
    2dup =
    if 2drop true exit then
    superclass dup 0=
  until
  2drop false
;

method isMemberOf ( class self -- bool)
  class =
;

method respondsTo ( message self -- bool)
  class canUnderstand
;

method instanceSize ( self -- num)
  class basicInstanceSize
;

method copy ( self -- object) 
  shallowCopy
;

method shallowCopy ( self -- object)
  here swap 2dup instanceSize dup allot cmove
;

method deepCopy ( self -- object)
  copy
;

method doesNotUnderstand ( message self -- )
  basicWrite ." does not understand: " .message cr abort
;

method subclassResponsibility ( message self -- )
  basicWrite ." subclass should have overridden: " .message cr abort
;

method shouldNotImplement ( message self -- )
  basicWrite ." should not implement: " .message cr abort
;

method perform ( message self -- )
  tuck class send
;
  
method write ( self -- )
  basicWrite
;

method basicWrite ( self -- )
  dup .class ." #" .
;

subclass.end


Object subclass Point ( x y -- )

  long +x ( self -- addr)
  long +y ( self -- addr)

method initiate ( x y self -- )
  dup >r super initiate r> position
;

method position ( x y self -- )
  tuck +y ! +x ! 
;

method where ( self -- x y)
  dup +x @ swap +y @
;

method write ( self -- )
  dup super write where ." x: " swap . ." :y " .
;

subclass.end


Object subclass Account ( x -- )

  long +owner ( self -- addr)
  long +balance ( self -- addr)

method initiate ( x self -- )
  dup >r super initiate r>
  0 over +balance ! +owner !
;

method balance ( self -- x)
  +balance @
;

method owner ( self -- x)
  +owner @
;

method deposit ( x self -- )
  +balance +!
;

method withdraw ( money self -- )
  swap negate swap +balance +!
;

method write ( self -- )
  dup super write
  ." owner: " dup owner $print space
  ." balance: " balance .
;

subclass.end

: DEBUG ;

#ifdef DEBUG

message traceOn ( object -- )
message traceOff ( objec -- )

nil subclass TraceableObject

  ptr +real-object ( object -- addr)
  long +trace ( object -- addr)

method initiate ( class self -- )
  >r new-instance r@ +real-object ! r> traceOff
;

method doesNotUnderstand ( message self -- )
  dup +trace @
  if 2dup +real-object @
    basicWrite ." called with the message: " .message cr
  then
  +real-object @ tuck class send
;

method traceOff ( object -- )
  false swap +trace !
;

method traceOn ( object -- )
  true swap +trace !
;

subclass.end

#else

: TraceableObject ;

#then

Object instance anObject
anObject write cr
anObject read
cr

10 10 Point instance aPoint
aPoint write cr
-10 -10 aPoint position
aPoint write cr
aPoint read 
cr

10 10 Point TraceableObject instance aTracedPoint
aTracedPoint traceOn
aTracedPoint write cr
-10 -10 aTracedPoint position
aTracedPoint write cr
aTracedPoint read
cr 

" Mikael" Account instance anAccount 
anAccount write cr
100 anAccount deposit
anAccount write cr
98 anAccount withdraw
anAccount write cr
cr

forth only

- - - - - - - - File: object.3 - - - - - - - - - - - - - - - - - 


OBJECTS(3X)      MISCELLANEOUS LIBRARY FUNCTIONS      OBJECTS(3X)



NAME
     objects - object oriented programming extension

SYNOPSIS
     #include objects.f83

     objects

DESCRIPTION
     This library realizes the popular  class-instance  model  of
     object  oriented  programming.  The  "world" is divided into
     classes and instances. The classes hold all common  informa-
     tion  for  the  instances.  This information is the instance
     variable fields and the messages an instance can answer. The
     answer  of  a  message is called a method. A method may call
     the super class implementation of a message with the  prefix
     word  "super".  This creates a static binding of the message
     to the super class. A messages require the object as the top
     most  parameter stack element and will locate an appropriate
     method at run-time (late-binding).

     : .class ( object -- )
          Displays the name of the class  of  an  object  on  the
          current output stream.

     : .message ( message -- )
          Displays the name of the message on the current  output
          stream. May be used by the error message "doesNotUnder-
          stand" which receives a message as parameter.

     : align ( -- )
          Instance variable layout control word.  Used  to  align
          the  next  field  to  an  even byte boundary within the
          definition section of a class.

     : basicInstanceSize ( class -- num)
          Returns the instance size in bytes.

     subclass.field byte ( -- )
          Used within the instance variable section  of  a  class
          definition to create a byte field name.
          byte <name> ( object -- addr)
          The field will require an object and  will  return  the
          address of the byte within the object.

     : bytes ( size -- )
          Used within the instance variable section  of  a  class
          definition to create a byte vector field name.
          <size> bytes <name> ( object -- addr)
          The field will require an object and  will  return  the
          address of the byte vector within the object.

     : canUnderstand ( message class -- bool)
          Returns "true" if the class can understand the  message
          (there exists a method) else "false".

     : class ( object -- addr)
          Returns the class address for the object. The class  is
          implemented as a prototype.

     forward doesNotUnderstand ( message object -- )
          Forward declared error message. Sent to an object  when
          the  message  lookup  mechanism  fails.  May be used to
          implement "proxy" objects.

     subclass.field enum ( -- )
          Used within the instance variable section  of  a  class
          definition to create a enumerate field name.
          enum <name> ( object -- addr)
          The field will require an object and  will  return  the
          address of the enumerate within the object.

     forward initiate ( ... object -- )
          This word is called by  "new-instance"  and  "instance"
          and  should  be  a  message  used to initiate the newly
          created object.

     : instance ( class -- )
          Used in the following form:
          <class> instance <name> ( -- object)
          to create a named instance  of  a  class.  The  message
          "initiate"  is send to the newly created instance. This
          message must be answered.

     subclass.field long ( -- )
          Used within the instance variable section  of  a  class
          definition to create a long integer field name.
          long <name> ( object -- addr)
          The field will require an object and  will  return  the
          address of the long integer within the object.

     : message ( -- )
          Used in the following form:
          message <name> ( ... object -- ... )
          to create a message. The message may be  passed  to  an
          object  as a normal function call. The top most parame-
          ter is always required to be an object.  A  method  for
          the message is located at run-time giving late binding,
          and polymorphism.

     : method ( -- )
          Used in the following form within the  definition  sec-
          tion of a class:
          method <message> ( ... object -- ...) ... ;
          to define a method for the  message.  The  method  will
          receive  the  object,  self, as the first parameter. To
          pass the message to the superclass the  message  prefix
          word  "super"  may  be used. This is common practice in
          object  oriented  programming.  The  method  definition
          should not contain the words "recurse", "tail-recurse",
          and "exception>" as these require an entry binding.

     : new-instance ( class -- object)
          Used in the following form:
          <class> new-instance ( -- object)
          to create an instance of a  class.  The  message  "ini-
          tiate" is sent to the newly created instance. This mes-
          sage must be answered or  the  error  message  "doesNo-
          tUnderstand" is sent to the instance.

     vocabulary objects ( -- )
          The object oriented extension  vocabulary.  Include  to
          the vocabulary search set, "context", to allow program-
          ming in the object oriented programming paradigm.

     subclass.field ptr  ( -- )
          Used within the instance variable section  of  a  class
          definition to create a pointer field name.
          ptr <name> ( object -- addr)
          The field will require an object and  will  return  the
          address of the pointer field within the object.

     : send ( object message class -- object)
          Primitive message sending function. Used by the  normal
          message-passing,  "message",  mechanism  to  locate and
          apply a method.

     : subclass ( superclass -- )
          Used in the following form:
          <class> subclass <name>
          { <instance-variable-field> }
          { <method> }
          subclass.end
          to initiate the definition of a class. This  definition
          should  contain  two major sections; the instance vari-
          able fields, and the instance methods. All field  names
          will  become  local  to  the  class.  The words "byte",
          "bytes", "enum", "word", "long"  and  "ptr"  should  be
          used  to  create  instance  variable field names. These
          will require an object  pointer  and  will  return  the
          address  of  the  corresponding field. The field should
          then be manipulated with the memory  access  functions.
          The word "align" may be used before a field name defin-
          ition to align it to an even byte boundary. The  method
          definition  section may contain implementations of mes-
          sages. A  method  may  be  viewed  as  a  normal  colon
          definition  with  the  extension that many definitions,
          methods, for the same name, message, may  exist  simul-
          taneous  and  the  selection  is  performed at run-time
          (late binding). The method should  always  receive  the
          object,  self,  as  the top most parameter. The message
          prefix word "super" may be used to call the super class
          implementation of a method. This binding is static. The
          word "this-class" may be used  to  access  the  current
          class.  The  method  may  not  use the words "recurse",
          "tail-recurse", and "exceptions>" as these  require  an
          entry binding.

     : subclass.end ( -- )
          Used in the following form:
          <class> subclass <name>
          { <instance-variable-field> }
          { <method> }
          subclass.end
          to finish the definition of a class. Additional methods
          and fields should not be defined after this word.

     : super ( -- ) immediate compilation
          Used in the following form within a method definition:
          super <message>
          to call a method for a message in the superclass.  This
          word should only be used inside of method definitions.

     : superclass ( class1 -- class2)
          Returns the address super class of the class. The value
          is "nil" for a root class.

     : this-class ( -- class) immediate
          Returns the address of the current  definitions  class.
          Will return "nil" outside of a class definition.

     subclass.field word ( -- )
          Used within the instance variable definition section of
          a class to create a word integer field name.
          word <name> ( object -- addr)
          The field will require an object and  will  return  the
          address of the word integer within the object.

INTERNALS
     Private definitions in the objects vocabulary;

     slot instance-size: ( class -- num) private
          Slot for a class (prototype) containing the  number  of
          byte for an instance of this class.

     slot instance-variables: ( class -- entry) private
          Slot for a class (prototype) containing  a  pointer  to
          the  last  defined  instance  variable field entry. The
          list of variables is terminated by the class itself.

     : subclass.field ( size -- ) private
          Use to create instance variable field type names. These
          field  types should only be used within a class defini-
          tion.

     variable the-class ( -- addr) private
          Used within a class definition section  to  access  the
          address of the current definition class. Outside of the
          definition section the variable  will  have  the  value
          "nil".

SEE ALSO
     tile(1), forth(3X), prototypes(3X).

NOTE
     The function list is sorted in ASCII  order.  The  type  and
     mode of the entries are indicated together with their param-
     eter stack effect.

WARNING
     This library contains forward declared words which should be
     supplied.   Check  that  your  definitions  vocabulary comes
     before the "objects" vocabulary when defining these words.

COPYING
     Copyright (C) 1990 Mikael R.K. Patel

     Permission is granted to make and distribute verbatim copies
     of  this  manual provided the copyright notice and this per-
     mission notice are preserved on all copies.

     Permission is granted to copy and distribute  modified  ver-
     sions of this manual under the conditions for verbatim copy-
     ing, provided also that the section  entitled  "GNU  General
     Public  License" is included exactly as in the original, and
     provided that the entire resulting derived work  is  distri-
     buted  under  the  terms of a permission notice identical to
     this one.

     Permission is granted to copy and distribute translations of
     this  manual  into  another language, under the above condi-
     tions for modified versions, except that the  section  enti-
     tled  "GNU  General  Public  License"  may  be included in a
     translation approved by the author instead of in the  origi-
     nal English.

AUTHOR
     Mikael R.K. Patel
     Computer Aided Design Laboratory (CADLAB)
     Department of Computer and Information Science
     Linkoping University
     S-581 83 LINKOPING
     SWEDEN
     Email: mip@ida.liu.se

dwp@willett.pgh.pa.us (Doug Philips) (08/23/90)

In <1990Aug21.170600.26447@ida.liu.se>, mip@IDA.LiU.SE (Mikael Patel) writes:
> Some of the latest postings have suggested using a prefix
> message-passing operator.

??? PREFIX message passing operator?  I haven't seen that go by, could
you elaborate?

>  10 10 Point instance aPoint 
> ...
> -10 10 aPoint moveTo
> 
> The style follows "normal" forth and there is, in principle, 
> no difference between a colon definition and a message on
> the "surface".

I think that belies an object orientation, but I've said that several
times already.  If you are going to put OOP on top of Forth, then how
much will OOP bend to fit and will it still be OOP when you are done.
And how much will you bend Forth to meet it "halfway"?  I think that
perhaps this is an unstated "obvious" question which we are answering
differently.

> I believe that we should look for the definition of a common
> object oriented extension for forth and then work on the real 
> problem: A library with reusable classes. 

I think that that is a good idea if we can reasonably agree on the
OOF extensions to build from.  I would hope that the low level
implementation would not be allowed to overly (if at all) influence
the OOP extensions.  I think that that would be a good test of Forth's
so called extensibility.  Personally I think it can be done.

>      : canUnderstand ( message class -- bool)
>           Returns "true" if the class can understand the  message
>           (there exists a method) else "false".
> 
>      forward doesNotUnderstand ( message object -- )
>           Forward declared error message. Sent to an object  when
>           the  message  lookup  mechanism  fails.  May be used to
>           implement "proxy" objects.
> 
> 
>      : send ( object message class -- object)
>           Primitive message sending function. Used by the  normal
>           message-passing,  "message",  mechanism  to  locate and
>           apply a method.

I don't quite understand why the ordering of message and object or class
on the stack isn't consistent.  Perhaps I should hold my questions until
the implementation is released.

-Doug

---
Preferred: ( dwp@willett.pgh.pa.us  OR  ...!{sei,pitt}!willett!dwp )
Daily: ...!{uunet,nfsun}!willett!dwp  [last resort: dwp@vega.fac.cs.cmu.edu]

mip@IDA.LiU.SE (Mikael Patel) (08/23/90)

In article <1568.UUL1.3#5129@willett.pgh.pa.us> dwp@willett.pgh.pa.us (Doug Philips) writes:
>
>??? PREFIX message passing operator?  I haven't seen that go by, could
>you elaborate?

The issue is how to apply messages. If we look at it from the syntax
level point of view we have to handle the parameters, the object, and
the message. Using an active message style (function) would look like
this:
	<parameters> <object> <message>
        "10 10 aPoint moveTo"
If the message is passive a prefix message-passing function could be 
used:
	<parameters> <object> SEND <message>
        "10 10 aPoint SEND moveTo"
Or even prefixing the object:
	<parameters> <message> SENDTO <object>
	"10 10 moveTo SENDTO aPoint"
I believe the first style to be the "natural" choice and it blends nicely
with forth.

>I think that belies an object orientation, but I've said that several
>times already.  If you are going to put OOP on top of Forth, then how
>much will OOP bend to fit and will it still be OOP when you are done.
>And how much will you bend Forth to meet it "halfway"?  I think that
>perhaps this is an unstated "obvious" question which we are answering
>differently.
>

Implementing a OOP extension will have to be a hybrid solution much
like C++, Simula, and Turbo Pascal 5.0. Data will be divided into 
the groups objects, and primitive data types such as integers, float, 
etc. Going all the way to a full object oriented language such as 
Smalltalk-80 puts a large overhead on the basic computational
model and we will lose "forth". We also have to decide if classes
should be objects. In this case we will need meta-classes. Most
hybrid languages such as the ones above view the class and a language
construct, not an object, and a large amount of the class information
is lost at compile-time. In forth we can take some advantage of
this information (instance-variable schema, super class pointer etc).

>> I believe that we should look for the definition of a common
>> object oriented extension for forth and then work on the real 
>> problem: A library with reusable classes. 
>
>I think that that is a good idea if we can reasonably agree on the
>OOF extensions to build from.  I would hope that the low level
>implementation would not be allowed to overly (if at all) influence
>the OOP extensions.  I think that that would be a good test of Forth's
>so called extensibility.  Personally I think it can be done.

What I am looking for (thinking about, and designing) is an extension
that is not bound to an implementation. More a specification of
an interface. So far I have designed and experimented with three basic 
models of OOP in forth; relations, prototypes (or also called slot based),
and the class-instance model. These are all available in the next 
release. I'm just doing some more testing (gamma-testing) and making
some more examples.

>I don't quite understand why the ordering of message and object or class
>on the stack isn't consistent.  Perhaps I should hold my questions until
>the implementation is released.
>

The order of the parameters to the class "messages" have the class as
the top parameter. The "send" function should locate the message given
the class.  The object is a parameter to the method (self). The
implementation of the word "message" could look something like this:
	
	: message ( -- )
	  create-message
	does> ( object message -- object)
          over class send
        ;

A message word is active and performs the send operation. But the "send"
word can also be used when creating proxy-objects. The "TraceableObject"
is an example of this. Allowing access to the message-passing mechanism
give more modeling freedom.

>-Doug

Thanks for your comments! I'd love to see some more postings on this
subject. We havn't come to the real hard decisions yet. Garbage Collection.
Persistence. Multiple inheritance. And of cause, a class hierarchy for
abstract data types; sets, tuples, mappings, and sequences.

Mikael

dwp@willett.pgh.pa.us (Doug Philips) (08/24/90)

In <1990Aug23.160723.437@ida.liu.se>, mip@IDA.LiU.SE (Mikael Patel) writes:
> The issue is how to apply messages. If we look at it from the syntax
> level point of view we have to handle the parameters, the object, and
> the message. Using an active message style (function) would look like
> this:
> 	<parameters> <object> <message>
>         "10 10 aPoint moveTo"
> If the message is passive a prefix message-passing function could be 
> used:
> 	<parameters> <object> SEND <message>
>         "10 10 aPoint SEND moveTo"
> Or even prefixing the object:
> 	<parameters> <message> SENDTO <object>
> 	"10 10 moveTo SENDTO aPoint"

Or even postfix:
	<parameters> <message> <object> SEND

> I believe the first style to be the "natural" choice and it blends nicely
> with forth.

This is what I have trouble with.  It is the same as advocating the
principle of least astonishment.  What will or won't astonish, or what will
or won't seem natural is in the eye of the beholder.  One of the points of
doing OOP is to use the OO paradigm.  That means that your old habits and
ideas about "naturalness" are not going to be correct in the OO world.  OOP
means looking at program methodology in a different way.  If you are going
to bend OOP into indirect-functional-call-Forth I doubt that you will attain
the new perspective.  The question I should have asked is:

    Why do you want to put OOP into Forth?  What do you think it
    will get for you that you don't already have?

Part of my answer is that I want to gain the reusability and encapsulation,
etc. from OOP and still have the nice Forth development environment.  Just
as C++ lets you link with C code and lets you gradually convert old
applications to OO style, so this would let you add OOP to existing Forth
code.  You might even mix OOF with some kind of Forth Expert Systems
extensions and with regular Forth code.  Despite, or perhaps especially
because of, that I do not want to invalidate the OOP perspective in the
process of providing it.  What would be the point?

> Implementing a OOP extension will have to be a hybrid solution much
> like C++, Simula, and Turbo Pascal 5.0. Data will be divided into 
> the groups objects, and primitive data types such as integers, float, 
> etc.

This is independant of syntax, since Forth is so totally free with letting
you roll your own.  I agree that making all primitive types into objects is
going overboard for Forth.  At that point you're probably better of hacking
a SmallTalk implementation to make the syntax post-fix.

>                                 We also have to decide if classes
> should be objects. In this case we will need meta-classes. Most
> hybrid languages such as the ones above view the class and a language
> construct, not an object, and a large amount of the class information
> is lost at compile-time. In forth we can take some advantage of
> this information (instance-variable schema, super class pointer etc).

You may only need one meta-class (Isn't that what XLisp does?  Its been too
long, I can't remember).  Depends on how sophisticated you want to get.
Maybe we could even have a layered approach.  Words that you can use if you
have the "classes as objects" extensions loaded.  I wonder how the
factoring for that would work out...

> What I am looking for (thinking about, and designing) is an extension
> that is not bound to an implementation. More a specification of
> an interface. So far I have designed and experimented with three basic 
> models of OOP in forth; relations, prototypes (or also called slot based),
> and the class-instance model. These are all available in the next 
> release. I'm just doing some more testing (gamma-testing) and making
> some more examples.

One of the reasons I started to complain about OOF extensions now was it
*seemed* like a lot of people were putting non-trivial work into them.  I
don't/didn't want to see all that effort go into implementing what I
perceive to be an inferior solution.  I was hoping that I could convince
some of the people now doing OOF's to refocus their goal before the
threshold of "I've put too much into into it to change now" was reached.  I
now think I failed.  I realize now that by the time any of that work was
announced a lot of effort had gone into it.  I suspect enough effort to
push it over the threshold.  I still hope otherwise, esp. since many OOF's
are less than 6 or so screens.  It really depends on how much code has been
developed that uses those OOF extensions.

>          We havn't come to the real hard decisions yet. Garbage Collection.
> Persistence. Multiple inheritance. And of cause, a class hierarchy for
> abstract data types; sets, tuples, mappings, and sequences.

I suspect that looking at the latest C++ (2.0, 2.1, 2.X?) might be informative.
Those people have thought hard about those issues.  C/C++ is not Forth,
I know that.  But they share many of the same goals, and many of the same
restrictions.

-Doug

---
Preferred: ( dwp@willett.pgh.pa.us  OR  ...!{sei,pitt}!willett!dwp )
Daily: ...!{uunet,nfsun}!willett!dwp  [last resort: dwp@vega.fac.cs.cmu.edu]


---
Preferred: ( dwp@willett.pgh.pa.us  OR  ...!{sei,pitt}!willett!dwp )
Daily: ...!{uunet,nfsun}!willett!dwp  [last resort: dwp@vega.fac.cs.cmu.edu]

mip@IDA.LiU.SE (Mikael Patel) (08/24/90)

In article <1602.UUL1.3#5129@willett.pgh.pa.us> dwp@willett.pgh.pa.us (Doug Philips) writes:

>    Why do you want to put OOP into Forth?  What do you think it
>    will get for you that you don't already have?
>
>Part of my answer is that I want to gain the reusability and encapsulation,
>etc. from OOP and still have the nice Forth development environment.  Just
>as C++ lets you link with C code and lets you gradually convert old
>applications to OO style, so this would let you add OOP to existing Forth
>code.  You might even mix OOF with some kind of Forth Expert Systems
>extensions and with regular Forth code.  Despite, or perhaps especially
>because of, that I do not want to invalidate the OOP perspective in the
>process of providing it.  What would be the point?

There exist a number of well established paradigms for programming 
today; functional, procedural, process, rule-based, logic, object-
oriented, and so on. Restricting oneself to programming in only one
paradigm is a mistake. All are valid, fruitful, and allow problems to
be solved quicker in their specific domain. Allowing object-orientation 
in forth is much like opening the door to concurrent programming. 
Being able to mix paradigms in the same language is a strength and 
not a weakness.

Forth has this wonderful nature of acting as a meta language and allow
all of these paradigm if they are needed. A common OOP extension will
allow use to reduce the otherwise very large name space in forth and
write reusable code. Who wants to have to rewrite lists, sets, etc?
It is the 90's not 70's.

>One of the reasons I started to complain about OOF extensions now was it
>*seemed* like a lot of people were putting non-trivial work into them.  I
>don't/didn't want to see all that effort go into implementing what I
>perceive to be an inferior solution.  I was hoping that I could convince
>some of the people now doing OOF's to refocus their goal before the
>threshold of "I've put too much into into it to change now" was reached.  I
>now think I failed.  I realize now that by the time any of that work was
>announced a lot of effort had gone into it.  I suspect enough effort to
>push it over the threshold.  I still hope otherwise, esp. since many OOF's
>are less than 6 or so screens.  It really depends on how much code has been
>developed that uses those OOF extensions.

I have seen a number of OOF implementation that have not impressed me.
As Mitch points out everyone has one. But to be able to take the next
step we must agree on a 'standard'. That is of the reasons these 
discussions are needed and valuable. If everyone has their own idea 
about OOF we will never be able to get up to the C++ or Smalltalk-80 
level and never ever to the system level of Smalltalk. And I don't
want to be negative!

Using forth gives us the advantage, compared to other language-addicts,
that we don't have to write a pile of code to get something done. To
demonstrate a concept etc. 6 screens (2-3 pages) is about the size of
most (any!) extensions to forth :-)

What is your suggestion? How should be go about attaching this problem?
I think that if more forth users and OOF implementors present and 
discuss their solutions we should be able to agree on a word set for
OOF.

We do need it! That's out of the question. But how?


>-Doug
>

-Mikael

dwp@willett.pgh.pa.us (Doug Philips) (08/29/90)

In <1990Aug24.133045.12494@ida.liu.se>, mip@IDA.LiU.SE (Mikael Patel) writes:

> Being able to mix paradigms in the same language is a strength and 
> not a weakness.

I never intended to claim it was, though perhaps you are not intending
to disagree with me here.

> I have seen a number of OOF implementation that have not impressed me.
> As Mitch points out everyone has one. But to be able to take the next
> step we must agree on a 'standard'. That is of the reasons these 
> discussions are needed and valuable. If everyone has their own idea 
> about OOF we will never be able to get up to the C++ or Smalltalk-80 
> level and never ever to the system level of Smalltalk. And I don't
> want to be negative!

Yes, we need to have agreement in order for more than one person to
work on building those things.  What is agreed upon is also important.

> What is your suggestion? How should be go about attaching this problem?
> I think that if more forth users and OOF implementors present and 
> discuss their solutions we should be able to agree on a word set for
> OOF.

I think you are right.  We need to get more than the few of us that
have been discussing OOF recently involved.  Pointers to literature
are also welcome.  I doubt that the scheme I propose has never been
proposed before.  I would like to see others.  Perhaps a ForthNet
wide OOF brainstorming session?  (i.e. what we've been doing but with
more people and more ideas?)

-Doug

---
Preferred: ( dwp@willett.pgh.pa.us  OR  ...!{sei,pitt}!willett!dwp )
Daily: ...!{uunet,nfsun}!willett!dwp  [last resort: dwp@vega.fac.cs.cmu.edu]