Sub-Go
view release on metacpan or search on metacpan
lib/Sub/Go.pm view on Meta::CPAN
if ( ref $_go_self->{rest} eq __PACKAGE__
&& !$_go_self->{yielded}
&& !$_go_self->{stop} )
{
if ( @$ret > 1 ) {
$_go_self->{by}
? $_go_self->{rest}->{code}->( @$ret )
: $ret ~~ $_go_self->{rest};
}
else {
return $_go_self->{ by }
? $_go_self->{rest}->{code}->( @$ret )
: $ret ~~ $_go_self->{rest};
}
}
elsif ( ref $_go_self->{rest} eq 'SCALAR' ) {
${ $_go_self->{rest} } = $ret->[0];
}
elsif ( ref $_go_self->{rest} eq 'ARRAY' ) {
@{ $_go_self->{rest} } = @$ret;
}
elsif ( ref $_go_self->{rest} eq 'HASH' ) {
%{ $_go_self->{rest} } = @$ret;
}
else {
return @$ret > 1 ? $ret
: $ret->[0] // $ret;
}
}
sub stop {
require PadWalker;
my $self_ref;
for ( 2 .. 3 ) {
my $h = PadWalker::peek_my( $_ );
$self_ref = $h->{ '$_go_self' } and last;
}
!$self_ref and croak 'Misplaced yield. It can only be used in a go block.';
my $self = ${ $self_ref };
$self->{stop} = 1;
return bless {}, 'Sub::Go::Break';
}
sub skip {
return bless {}, 'Sub::Go::Break';
}
sub yield {
require PadWalker;
my $self_ref;
for ( 2 .. 3 ) {
my $h = PadWalker::peek_my( $_ );
$self_ref = $h->{ '$_go_self' } and last;
}
!$self_ref and croak 'Misplaced yield. It can only be used in a go block.';
my $self = ${ $self_ref };
$self->{yielded} = 1;
$self->{rest}->{code}->( @_ );
}
sub go(&;@) {
my $code = shift;
my $rest = shift;
return bless { code => $code, rest => $rest }, __PACKAGE__;
}
sub by(&;@) {
my ( $code, $rest ) = @_;
return bless { code => $code, rest => $rest, by => 1 }, __PACKAGE__;
}
1;
=pod
=head1 NAME
Sub::Go - DWIM sub blocks for smart matching
=head1 VERSION
version 0.01
=head1 SYNOPSIS
use Sub::Go;
[ 1, 2, 3 ] ~~ go { say $_ };
# 1
# 2
# 3
# hashes with $a and $b
%h ~~ go { say "key $a, value $b" };
undef ~~ go {
# never gets called...
};
'' ~~ go {
# ...but this does
};
# in-place modify
my @rs = ( { name=>'jack', age=>20 }, { name=>'joe', age=>45 } );
@rs ~~ go { $_->{name} = 'sue' };
# filehandles
open my $fh, '<', 'file.txt';
$fh ~~ go {
my $line = shift;
say ; # line by line
};
# chaining
@arr ~~ go { s/$/one/ } go { s/$/two/ };
# combine with signatures, or Method::Signatures
# for improved sweetness
use Method::Signatures;
%h ~~ go func($x,$y) {
say $x * $y;
};
( run in 2.163 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )