NAME
Sub::Go - DWIM sub blocks for smart matching
VERSION
version 0.01
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;
};
DESCRIPTION
In case you don't know, smart matching (~~) data against a code block will run the block once (for scalars) or, distributively, many times for arrays and hashes:
[1..10] ~~ sub { say shift };
@arr ~~ sub { say shift };
%h ~~ sub { ... };
The motivation behind this module is to improve the experience of using a code block with the smart match operator.
This module imports a sub called go into your package. This sub returns an object that overloads the smart match operator.
Benefits
proper handling of hashes, with $a and $b for keys and values
Smart matching sends only the keys, which may be useless if your hash is anonymous.
{ foo=>1, bar=>2 } ~~ go { 
     say "key=$a, value=$b";
};
context variables
Load $_ with the current value for arrays and scalars. Look for $a and $b for hash values.
in-place modification of original values
But only in the first go block of a chain (although this may change soon).
my @arr = qw/a b c/;
@arr ~~ go { s{$}{x} };
# now @arr is qw/ax bx cx/
prevent the block from running on undef values
We're tired of checking if defined is defined in loops.
undef ~~ go { say "never runs" };
undef ~~ sub { say "but we do" };
chaining of sub blocks
So you can bind several blocks, one after the other, in the opposite direction of map, grep and friends.
$arr ~~ go { } go { } go { };
no warnings on the useless use of smart match operator in void context
Annoying warning for funky syntax overloading modules like this one or IO::All. Perl should have better way around this warning.
Pitfalls
A smart match (and most overloaded operators) can only return scalar values. So you can only expect to get a scalar (value or arrayref) from your block chaining.
FEATURES
chaining
You can chain go statements together, in the reverse direction as you would with map or grep.
say 10 ~~ go { return $_[0] * 2 }
            go { return $_[0] + 1 }; 
# 21  
The next go block in the chain gets the return value from the previous block.
[1..3] ~~ go { say "uno " . $_[0]; 100 + $_[0] }
          go { say "due " . shift };
# uno 1    
# uno 2    
# uno 3    
# due 101
# due 102
# due 103
To interleave two go blocks use the yield statement.
[1..3] ~~ go { say "uno " . $_[0]; yield 100 + $_[0] } go { say "due " . shift };
# uno 1    
# due 101
# uno 2    
# due 102
# uno 3    
# due 103
You can interrupt a go block with an special return statement: return skip.
[1..1000] ~~ go {
    # after 100 this block won't execute anymore
    return skip if $_[0] > 100;
} go {
    # but this one will keep going up to the 1000th
};
Or break the whole chain at a given point:
[1..1000] ~~ go {
    # after 100 this block won't execute anymore
    return stop if $_[0] > 100;
} go {
    # this one will run 100 times too
};
return values
Scalar is the only return value from a smart match expression, and the same applies to go. You can only return scalars, no arrays and hashes. So we return an arrayref if your go chain returns more than one value.
# scalar
my $value = 'hello' ~~ go { "$_[0] world" } # hello world
# arrayref 
my $arr = [10..19] go { shift }; # @arr == 1, $arr[0] == 10
Just use 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 map like interface the other way around.
next iterators
If you send the block an object which implements a method called 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!";
};
IMPORTS
go CODE
The main function here. Don't forget the semicolon at the end of the block.
yield VALUE
Iterate over into the next block in the chain.
[qw/sue mike/] ~~ go { yield "world, $_" } go { say "hello " . shift };
skip
Tell the iterator to stop executing the current block and go to the next, if any.
return skip;
stop
Tell the iterator to stop executing all blocks.
return stop;
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.
PadWalker, a dependency, may segfault in perl 5.14.1.
SEE ALSO
autobox::Core - has an each method that can be chained together