[self-interest] objects are cheap (was: Nil)

Jecel Assumpcao Jr jecel at lsi.usp.br
Mon Jul 26 19:37:21 UTC 1999

On Wed, 07 Jul 1999 15:53:16 -0300 Douglas Atique wrote:
> I have been making small programs in C++ which used the Standard Library
> collections,
> in which I represented both "undefined" and "non-existent" contained objects
> with NULL. I have also read some article about dropping the NULL and using a
> NullObject class in place of it, but it seemed cumbersome to have an object
> instantiated just for that. Objects seemed just too expensive to "throw away"
> like that. Now I am changing my mind about the efficiency concerns vs. ease of
> programming and clearness of representation. It's because in Self one thinks
> in terms of objects only and not in terms of classes or data. [...]

This is a very important point. It is too costly to make a new
class to "reify" some concept in an applications, but we can make
as many new (prototype) objects we want with no worries. For
example, if we need to return three values from a method we can
simply create a new kind of object with three data slots, stuff
it with the values and then return this object as the result.

A lot of my Self programs show some bad habits that I picked up
with other languages. I'll give an example from the Self UI
instead, however, to save myself some well deserved embarrassment ;-)

If you look at a simple morph, you will see two slots called
'hResizing' and 'vResizing'. They can have as values the integers
0 (meaning rigid), 1 (meaning flexible) or 2 (meaning shrinkWrap).
This is all very nice, but we have to have methods in traits morph

   isFlexibleHorizontally = (1 = hResizing)


   layoutDescription = ( | r |
              r: 'h: '.
              isRigidHorizontally       ifTrue: [ r: r,      'rigid'].
              isFlexibleHorizontally    ifTrue: [ r: r,   'flexible'].
              isShrinkWrapHorizontally  ifTrue: [ r: r, 'shrinkWrap'].

              r: r, ', v: '.
              isRigidVertically         ifTrue: [ r: r,      'rigid'].
              isFlexibleVertically      ifTrue: [ r: r,   'flexible'].
              isShrinkWrapVertically    ifTrue: [ r: r, 'shrinkWrap'].


Now imagine that we had three little objects called 'rigid',
'flexible' and 'shrinkWrap', where some of the slots in 'flexible'
could be:

   flexible = ( |
                  isRigid = false.
                  isFlexible = true.
                  isShrinkWrap = false.
                  name = 'flexible'.
              | )

We could replace the expression 'isFlexibleHorizontally' with
'hResizing isFlexible' (though some people would object that I
am "breaking the morph's encapsulation", here) and we would have
a method:

     layoutDescription = ( 'h: ', hResizing name,
                           ', v: ', vResizing name )

which looks much nicer to me. By adding a few more methods to
our three new helper objects, there are several more methods in
'traits morph' and 'spaceAllocator' that could be made slightly
simpler as well. Is it worth doing this? Not in Smalltalk, C++ or
Java. But I would vote for this programming style when the language
is Self.

-- Jecel

More information about the Self-interest mailing list