[erlang-questions] Fear and Loathing in Programming La La Land

Richard O'Keefe ok@REDACTED
Sat Mar 31 03:59:51 CEST 2012


On 31/03/2012, at 10:04 AM, David Goehrig wrote:

> "exposing incompletely initialised objects"
> 
> Which is why in a functional language with partial application, any constructor w/ parameters is kinda silly.  Sometimes I really want a partially initialized object to clone.

Please give a concrete example.

Remember the basic distinction here:

 a class has a class invariant relating all the fields

 full initialisation establishes the entire class invariant

 partial initialisation establishes at most that part of the
   class invariant referring to a subset of the fields

Here is a concrete example.

    Object subclass: #Complex
      instanceVariableNames: 're im'
      gettable:              're im'
      settable:              're im'
      methods:
        invariant
          ^(re isKindOf: Number) and: [im isKindOf: Number]
        ... a bunch of arithmetic methods ...
      ... inherited #new method ...

You seem to be arguing that

      z := Complex new.
      z re: 0.0.
      i := z copy.
      i im: 1.0.
      minus_i := z copy.
      minus_i im: -1.0.

is a good idea.  In this example, the default #new method returned
an object for which (z invariant) is false, the re and im fields
being nil.  Cloning and copying aren't exactly the same thing, and
confusingly, Java uses the name 'clone' for what's really a 'copy'.

The problem here is that now the #copy operation has to do something
sensible with an incompletely initialised object.  And so does the
#+ method.  And the #arcCosh method.  And so on, for another fifty-
odd methods.  So now we have to change the definition slightly:

      methods:
        pvtPostNew
          re := im := 0.0.

so that the default #new method (which calls #pvtPostNew, which is
pretty much the analogue of Objective-C's [_ init]) fully establishes
the invariant.

But now this is no longer a case of PARTIAL initialisation.  It is a
case of DEFAULT initialisation to something which is fully operational.
And you know, 'cloning' a fully initialised object works even better
than 'cloning' a partially initialised one, because now the #copy
method gets to assume that the invariant is true.

In strict point of fact, the actual definition is

    Object valueSubclass: #Complex
      instanceVariableNames: 're im'
      gettable:              're im'

and there is no possibility of changing a complex number, which is
actually pretty vital for the way they are normally used.

So can we please have a CONCRETE example from actual pre-existing code
of a situation where

 - there is some kind of "thing" which is more than just a bundle
   of independent items
 - it makes sense to create a "thing" that is not fully initialised
   (that is, the information in the call that builds its initial
   state is not sufficient to determine values that make the
   invariant true)
 - it makes sense to perform any operation on such a "thing" in such
   a state other than to move closer to a fully initialised state
 - it makes sense to allow all initialisation commands at all times, OR
 - the burden of checking which operations are allowable in which states
   is acceptable.
     
> I've been playing around with an OO approach to Erlang, where each process is a bare loop and all state/capabilities are injected at runtime via messaging.  With a prototype model  it turns out partial initialization is a big win, as it allows for incremental differentiation.

Again, please provide a concrete example.  Full initialisation ALSO allows
for incremental differentiation.

Continuing with the file stream example, it *might* make sense for

    r := FileReader new.
    r read: 'foo/bar.txt'.

to work by initially connecting r to /dev/null and having #read: be
like C's freopen(): close the current connection and establish a new
one.  That would be default-but-FULL-initialisation, not partial
initialisation.

In my own code, I've found it astonishing how rare it is for a plain
setter to make sense.  A little thought almost always shows that there
is *something* to check.


More information about the erlang-questions mailing list