Constructing objects: Chicken and egg

Computer

I recently had a tip from Nat Pryce about a weird control construct from HScheme: call-with-result. It passes into a function an argument which is its own result. Erm, okay. Let’s just think about that for a second. It solves the “chicken and egg” problem of creating mutual references between objects - something you’re normally forced to use setters for. We can use something like this to get better encapsulation.

So why do we need setters? It’s to fix up those “back” references. If you create an object (say in Java) you can pass into its constructor any objects it needs to “know” about during its lifetime, thus hiding the fact that that reference is there. Good encapsulation. What you can’t do is get two objects (Chicken and Egg) constructed with references to each other. One has to be constructed first (say Chicken), then the other (Egg). Chicken can’t be given Egg in its constructor because Egg doesn’t exist yet, so it needs a setEgg method. And now clients of Chicken can potentially start messing with its innards. An unpleasant thought on more than one level. Nat puts it better in his blog.

Let’s look at what call-with-result does. call-with-result is a special function in HScheme which calls another function with a reference to the result the called function is going to compute! Internally, this works by creating a reference before the inner function is called, and then fixing up the reference to point to whatever was returned after the function finishes. While the function is executing it can use a reference to the result it’s working on computing, but can’t dereference it in any way (i.e. you can store the reference but that’s about it).

From the HScheme website, a little program that adds the symbol hello to the start of the list the function will compute. This creates an infinitely long list (well, really a circular list whose tail points to itself) in just one step.

(call-with-result (lambda (rest) (cons 'hello rest)))

I’ve been interested in constructs like this for a while now, since I realized it’s nice to be able to create self-referencing and mutually-self-referencing object graphs without the need for setter methods. Setters force you to use state (in the form of variables) which you don’t always want, and they expose internal details - you might not want other objects to be able to use the setters.

Here’s how Chicken and Egg look in Kew:

Results do [
    :Chicken -- this is an argument to this block, but also its 1st result
    :Egg -- and this is the second result / argument

    ^{ -- create the first object, which will be Chicken
        getEgg [ -- return reference to Egg
            ^Egg
        ]
    }

    ^{ -- create Egg
        getChicken [ -- return the reference to Chicken
            ^Chicken
        ]
    }
] :MyChicken :MyEgg.

And now MyChicken getEgg and MyEgg getChicken work perfectly, and nobody had to create a variable (the names above are not mutable in Kew) or provide a setter. And because we have multiple results in Kew, we can create as many self-referencing objects as we like.

And the reason I worry about variables is that I’m trying to add transactions. It would be annoying if an object-pair like Chicken and Egg were created in a transaction, only to half-break due to using a variable when the transaction rolls back.

Update

Kew’s syntax and idioms have changed a lot and I would now write:

Chicken Egg: {
    egg: ^Egg
} {
    chicken: ^Chicken
};

… though this isn’t as general as Results do.