Perl-Apollo / Corinna

Corinna - Bring Modern OO to the Core of Perl
Artistic License 2.0
157 stars 19 forks source link

Open Questions: Readers with custom writers #13

Closed Ovid closed 4 years ago

Ovid commented 4 years ago

Please leave feedback regarding question 2 on this ticket.

haarg commented 4 years ago

This seems to be describing a general problem with argument handling in perl, not anything tied to Cor. While it would definitely be nice to improve the sub signature features to make this more reasonable, I wouldn't try to make it part of the Cor proposal. If you did want Cor to do something to solve this, something analogous to coercions seems like the way to do it.

Another way this could be written, which is admittedly a bit weird:

has $left :isa('BinaryTree');

method left ($child = return $left) {
    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;
}

This is very similar to the proposed "solution" except using perl's normal sub signature features, and not relying on a horrifying special case.

Ovid commented 4 years ago

I've never liked the = return hack because it really only works if you have an arity of 1 or 2. With an arity of 1, 2, or 3, this hack doesn't work:

method foo ($new_x = return $x, $new_y = return $y) {
   ...
}

mst pointed out the cleanest solution and one that is generally applicable:

has $foo :isa(Str); # no reader or writer
method foo(@args) {
    return $foo unless @args;
    ...
}

For now, I believe this issue is resolved.

tobyink commented 4 years ago

I've basically been going through examples of stuff that's hard in Cor, and seeing how Zydeco handles them. Has helped me catch a few bugs. Anyway, for the binary tree example on the Wiki...

use v5.16;
use Data::Dumper;

package Local::App {
    use Zydeco declare => ['BinaryTree'];

    class BinaryTree {

        method $add_child ( $value ) {
            $value->parent($self);
        }

        has value        ( is => rw, type => Value );
        has left, right  ( is => rw, type => BinaryTree, trigger => $add_child );
        has parent       ( is => rw, type => BinaryTree, weak_ref => true );

        coerce from Value via promote {
            $class->new( value => $_ );
        }       
    }
}

my $btree = Local::App->new_binarytree( value => 10 );
my $left  = $btree->left(3);
my $right = $btree->right(17);
$left->left(1);
$left->right(17);

print Dumper($btree);