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 )