Perl-Apollo/Corinna

Open Questions: Readers with custom writers

Ovid opened this issue · 3 comments

Ovid commented

Please leave feedback regarding question 2 on this ticket.

haarg commented

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

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.

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);