Sub-Go
view release on metacpan or search on metacpan
lib/Sub/Go.pm view on Meta::CPAN
while ( my ( $k, $v ) = each %$arg ) {
local $_ = [$k,$v];
( *$caller_a, *$caller_b ) = \( $k, $v );
push @$ret, $code->( $k, $v );
}
}
elsif ( ref $arg eq 'GLOB' ) {
while ( <$arg> ) {
my $r = $code->( $_ );
last if ref $r eq 'Sub::Go::Break';
push @$ret, $r;
}
}
elsif ( ref $arg eq 'CODE' ) {
for ( $arg->() ) {
my $r = $code->( $_ );
last if ref $r eq 'Sub::Go::Break';
push @$ret, $r;
}
}
elsif ( blessed $arg && $arg->can('next') ) {
while( local $_ = $arg->next ) {
push @$ret, $code->( $_ );
}
} else {
push @$ret, $code->( $arg ) for $arg;
}
# chaining return value processing
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
lib/Sub/Go.pm view on Meta::CPAN
my $arr = [10..19] go { shift }; # @arr == 1, $arr[0] == 10
Just use C<map> in this case, which is syntactically more sound anyway.
So, there's an alternative implementation for returning values, by
chaining a reference to a variable, as such:
my @squares;
@input ~~ go { $_ ** 2 } \@squares;
my %hash = ( uno=>11, due=>22 );
my %out;
%hash ~~ go { "xxx$_[0]" => $_[1] } \%out;
# %out = ( xxxuno => 11, xxxdue => 22 )
Now you have a C<map> like interface the other way around.
=head2 next iterators
If you send the block an object which implements
a method called C<next>, the method will be automatically called
and the return value fed to the block.
# DBIx::Class resultset
$resultset->search({ age=>100 }) ~~ go {
$_->name . " is centenary!";
};
=head1 IMPORTS
=head3 go CODE
The main function here. Don't forget the semicolon at the end of the block.
=head3 yield VALUE
Iterate over into the next block in the chain.
[qw/sue mike/] ~~ go { yield "world, $_" } go { say "hello " . shift };
=head3 skip
Tell the iterator to stop executing the current block and go
to the next, if any.
return skip;
=head3 stop
Tell the iterator to stop executing all blocks.
return stop;
=head1 BUGS
This is pre-alfa, out in the CPAN for a test-drive. There
are still inconsistencies in the syntax that need some
more thought, so expect things to change badly.
L<PadWalker>, a dependency, may segfault in perl 5.14.1.
=head1 SEE ALSO
L<autobox::Core> - has an C<each> method that can be chained together
L<List::Gen>
L<Sub::Chain>
=cut
( run in 2.089 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )