[net.micro] Up with Object Orientedness!

mdrutenberg (12/08/82)

Don -


I have been reading over some of your messages and I want to try to
clear up some of the things you were saying about Smalltalk.  While I am
not a language expert in general, I have used Smalltalk-80 and know some
things about it.  So, here is a little stuff to think about until I
finish exams and have more time for real discussions.

First I want to start off with a general note that Smalltalk-80 is not
@i(just) a language but is also an integrated computing environment.  I
think there are some very interesting ideas in both of these which are
'new' in that they haven't really shown up cleanly built into a programming
language and/or environment before.  There are also refinements to some
things which have been around for some time.


So here we go...

First I think it would be helpful to give some examples for people to
think about.

You mention the example of "sqrt(5)" in your last message.  What we
ideally want to do, as you indicate, is to specify @i(what) you want to
do rather than @i(how) exactly to do it.  You mention that Pascal's
"sqrt(5)" says that we want to calculate the square root of 5 but does
not indicate how it is done.  I would disagree that this, in Pascal, is
not specifying how it is being done, since for example I can't say
"sqrt(numb)" where numb is a variable of type "extended precision
integer" which I have defined. The compiler will choke and tell me that
it must be of type real.  I will instead have to create my own function,
possibly called 'longIntSqrt', which can find the square roots of long
integers and in doing so I am specifying @i(how) I do things rather than
just what I want to do.

As a real live example in Smalltalk-80, consider the following class
hierarchy (I hope everyone has nonproportional fonts so this looks ok):


                                     Object
                                     /    \
                                    /   <<other classes>>
                                   /
                               Magnitude
                               /       \
                              /      <<other classes such as date, time>>
                             /
                          Number
			/   |   \
                       /    |    \
                      /     |     \
               Fraction   Float  Integer


If I want to calculate the function

                  2 sin x
	foo(x) = e

for any number x, I want to be able to say foo(x) or similar, and have
it give me the right result for @i(any) type of x.  In Smalltalk I would
put the following definition in class Number:

      foo
          "calculate the well known foo function"
       
          ^ (self sin  *  2) exp

At this point, @i(any) of the numbers in the chart above can now
calculate it's foo value and each type of number will use this same
piece of code since all numbers inherit behaviour from class Number.
Also - If last Saturday night I got fed up with those short little @i(n)
digit reals I'm given by every computer manufacturer, and I created a
type of number called LargeFloat which responds to all the standard
messages that a Float does and provides me with 1000+ digits, one of
those numbers also can tell me it's foo value with no extra work done by
me, again using this same piece of code.  <<note: In Smalltalk, 'self'
refers to the receiver of the message>>.


Another interesting things occurs with routines like factorial.  For some
background, which you will (almost?) never need to know:
	                                       65536       65536
	Integers in the system have a range -10       to 10
	Because most integers are quite close to zero, there is a
	special class called SmallInteger for these which is specially
	handled (i.e. is fast), but from the outside they look @i(just)
	like any other integer.  If, for example, we multiply two SmallIntegers
	together, and the product is out of range for a SmallInteger, then
	we are instead returned a LargeInteger which has the correct value.
	When using system, you have only the idea of "integers".

Back to the example of factorial - Consider a routine to find the
factorial of an integer as follows:

     factorial
         "Return my factorial, which is the product of all the positive
          integers less than or equal to myself"

	self > 0
            ifTrue: [^self * (self - 1) factorial].

	self = 0
            ifTrue: [^1].   "0! = 1"

	self error: 'One can''t take the factorial of a negative number'


We know from experience that the factorial of an integer is usually
quite large.  We can (and should if we program computers) ask ourselves
then - "What will happen when I ask a reasonably large integer, say one
hundred or one thousand, what it's factorial is?".  Well... at least in
Smalltalk we will get the right answer!

If we ask what 100! is, we will recurse and the start multiplying.  At
some point, the product of the intermediate result, (self - 1) factorial,
and the current number, self, will exceed the range of SmallIntegers.
The correct result of the multiply will be returned in spite of this in
the form of a LargeInteger, and your program just keeps on working.  I
have used this to find the number of zeroes in 1000! and if there is
popular demand, I'll include this in my next message.



Mike Rutenberg
	a.k.a.  Arpanet:     decvax!watmath!mdrutenberg@berkeley
		Usenet:  ...!decvax!watmath!mdrutenberg


P.S.  It should be noted that some of this stuff can be done in other
languages, like (?) Generic Procedures in Ada or (?) Bignums in
Interlisp.  I would love to see what these examples would look like in
<<what you use>>.  If you'll mail them to me, I will collect them
together and post it.