Skip to content

Questions

Ovid edited this page May 16, 2020 · 11 revisions

Open Questions About Cor

Unitialized versus Undefined

It's rare, but if a slot (has $foo :predicate) can be undef, we probably want the predicate method to return true for has_foo. Otherwise, we can't distinguish between an intentional undefined value and and an unset value.

Readers With Custom Writers

In general, Cor wants immutable objects. In practice, sometimes this is hard. For example, in the case of a Binary Tree, you want to be able to add a new node. Let's imagine an integer tree. How might we use that?

my $tree  = BinaryTree->new( value => 10 );
my $left  = $tree->left(3);
my $right = $tree->right(17);
$left->left(1);
$left->right(17);

And that might represent a tree like this:

         10
        /  \
       3   17
      / \
    1   17

So far, so good. If you're traversing the tree, you might want to check out a node's value:

if ( $node->left->value == $target ) {
    ...
}

In other words, this fits the common Perl paradigm of "faking" method overloading. For other language, we might have this:

method left () {
    # just return the left node
    return $left;
}

method left ($child) {
    # Set the value of the left node. If it doesn't exist,
    # create it and and set the parent to $self
    # if $child is already a binary tree, ensure that it doesn't
    # already have a parent
}

But we don't have method overloading in Perl. So we do variants of this:

sub left {
    my ( $self, $child ) = @_;
    if ( @_ > 1 ) {
        if ( blessed $child && $child->isa('BinaryTree') ) {
            croak(...) if $child->has_parent; # we don't reparent binary trees
        }
        else {
            $child = BinaryTree->new( value => $child );
        }
        $child->parent($self);
    }
    else {
        return $self->{left};
    }
}

That's very easy to get wrong. For example, you might test if $child is defined instead of how many arguments are passed to the method. That means you're never allowe

Now how do we declare the left and right slots and attributes?

This doesn't work:

has $left :reader :writer :isa('BinaryTree');

For the above, we have to allow the writer to accept a raw value or a binary tree. Cor is not (at this time) offering coercions or triggers. Further, given that so many languages have no problem with this, it's clearly not a requirement that we have coercions or triggers.

This also doesn't work:

has $left :reader :isa('BinaryTree');

method left ($child) {
    if ( blessed $child && $child->isa('BinaryTree') ) {
        croak(...) if $child->has_parent; # we don't reparent binary trees
    }
    else {
        $child = BinaryTree->new( value => $child );
    }
    $child->parent($self);
    return $left = $child;
}

Well, not only is that a touch ugly, but it's also method overloading in disguise.

Clone this wiki locally