view release on metacpan or search on metacpan
local/lib/perl5/Future/Phrasebook.pod view on Meta::CPAN
sub func {
foreach my $item ( @LIST ) {
if( COND($item) ) {
return $item;
}
}
return MAKE_NEW_ITEM();
}
The C<Future::Utils::call_with_escape> function allows this general form of
control flow, by calling a block of code that is expected to return a future,
and itself returning a future. Under normal circumstances the result of this
future propagates through to the one returned by C<call_with_escape>.
However, the code is also passed in a future value, called here the "escape
future". If the code captures this future and completes it (either by calling
C<done> or C<fail>), then the overall returned future immediately completes
with that result instead, and the future returned by the code block is
cancelled.
my $f = call_with_escape {
my $escape_f = shift;
( repeat {
my $item = shift;
COND($item)->then( sub {
my ( $result ) = @_;
if( $result ) {
$escape_f->done( $item );
}
return Future->done;
})
} foreach => \@ITEMS )->then( sub {
MAKE_NEW_ITEM();
});
};
Here, if C<$escape_f> is completed by the condition test, the future chain
returned by the code (that is, the C<then> chain of the C<repeat> block
followed by C<MAKE_NEW_ITEM()>) will be cancelled, and C<$f> itself will
receive this result.
=head1 CONCURRENCY
This final section of the phrasebook demonstrates a number of abilities that
are simple to do with C<Future> but can't easily be done with regular
call/return style programming, because they all involve an element of
concurrency. In these examples the comparison with regular call/return code
local/lib/perl5/Future/Utils.pm view on Meta::CPAN
use Exporter 'import';
# Can't import the one from Exporter as it relies on package inheritance
sub export_to_level
{
my $pkg = shift; local $Exporter::ExportLevel = 1 + shift; $pkg->import(@_);
}
our @EXPORT_OK = qw(
call
call_with_escape
repeat
try_repeat try_repeat_until_success
repeat_until_success
fmap fmap_concat
fmap1 fmap_scalar
fmap0 fmap_void
);
local/lib/perl5/Future/Utils.pm view on Meta::CPAN
our @CARP_NOT = qw( Future );
use Future;
=head1 NAME
C<Future::Utils> - utility functions for working with C<Future> objects
=head1 SYNOPSIS
use Future::Utils qw( call_with_escape );
my $result_f = call_with_escape {
my $escape_f = shift;
my $f = ...
$escape_f->done( "immediate result" );
...
};
Z<>
use Future::Utils qw( repeat try_repeat try_repeat_until_success );
my $eventual_f = repeat {
my $trial_f = ...
return $trial_f;
local/lib/perl5/Future/Utils.pm view on Meta::CPAN
completeness).
=cut
sub call(&)
{
my ( $code ) = @_;
return Future->call( $code );
}
=head2 call_with_escape
$f = call_with_escape { CODE }
I<Since version 0.22.>
The C<call_with_escape> function invokes a block of code that returns a
future, and passes in a separate future (called here an "escape future").
Normally this is equivalent to the simple C<call> function. However, if the
code captures this future and completes it by calling C<done> or C<fail> on
it, the future returned by C<call_with_escape> immediately completes with this
result, and the future returned by the code itself is cancelled.
This can be used to implement short-circuit return from an iterating loop or
complex sequence of code, or immediate fail that bypasses failure handling
logic in the code itself, or several other code patterns.
$f = $code->( $escape_f )
(This can be considered similar to C<call-with-escape-continuation> as found
in some Scheme implementations).
=cut
sub call_with_escape(&)
{
my ( $code ) = @_;
my $escape_f = Future->new;
return Future->wait_any(
Future->call( $code, $escape_f ),
$escape_f,
);
}
=head1 REPEATING A BLOCK OF CODE
The C<repeat> function provides a way to repeatedly call a block of code that
returns a L<Future> (called here a "trial future") until some ending condition
is satisfied. The C<repeat> function itself returns a C<Future> to represent
running the repeating loop until that end condition (called here the "eventual
future"). The first time the code block is called, it is passed no arguments,
local/lib/perl5/Module/Build/PPMMaker.pm view on Meta::CPAN
print "Using default codebase '$distfile'\n";
@codebase = ($distfile);
}
my %dist;
foreach my $info (qw(name author abstract version)) {
my $method = "dist_$info";
$dist{$info} = $build->$method() or die "Can't determine distribution's $info\n";
}
$self->_simple_xml_escape($_) foreach $dist{abstract}, @{$dist{author}};
# TODO: could add <LICENSE HREF=...> tag if we knew what the URLs were for
# various licenses
my $ppd = <<"PPD";
<SOFTPKG NAME=\"$dist{name}\" VERSION=\"$dist{version}\">
<ABSTRACT>$dist{abstract}</ABSTRACT>
@{[ join "\n", map " <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
<IMPLEMENTATION>
PPD
local/lib/perl5/Module/Build/PPMMaker.pm view on Meta::CPAN
# We only include these tags if this module involves XS, on the
# assumption that pure Perl modules will work on any OS.
if (keys %{$build->find_xs_files}) {
my $perl_version = $self->_ppd_version($build->perl_version);
$ppd .= sprintf(<<'EOF', $self->_varchname($build->config) );
<ARCHITECTURE NAME="%s" />
EOF
}
foreach my $codebase (@codebase) {
$self->_simple_xml_escape($codebase);
$ppd .= sprintf(<<'EOF', $codebase);
<CODEBASE HREF="%s" />
EOF
}
$ppd .= <<'EOF';
</IMPLEMENTATION>
</SOFTPKG>
EOF
local/lib/perl5/Module/Build/PPMMaker.pm view on Meta::CPAN
# Append "-5.8" to architecture name for Perl 5.8 and later
if ($] >= 5.008) {
my $vstring = sprintf "%vd", $^V;
$vstring =~ s/\.\d+$//;
$varchname .= "-$vstring";
}
return $varchname;
}
{
my %escapes = (
"\n" => "\\n",
'"' => '"',
'&' => '&',
'>' => '>',
'<' => '<',
);
my $rx = join '|', keys %escapes;
sub _simple_xml_escape {
$_[1] =~ s/($rx)/$escapes{$1}/go;
}
}
1;
__END__
=head1 NAME
Module::Build::PPMMaker - Perl Package Manager file creation
local/lib/perl5/Module/Build/Platform/VMS.pm view on Meta::CPAN
# or if we get a single arg that is an array reference, quote the
# elements of it and return the reference.
my ($self, @args) = @_;
my $got_arrayref = (scalar(@args) == 1
&& ref $args[0] eq 'ARRAY')
? 1
: 0;
# Do not quote qualifiers that begin with '/'.
map { if (!/^\//) {
$_ =~ s/\"/""/g; # escape C<"> by doubling
$_ = q(").$_.q(");
}
}
($got_arrayref ? @{$args[0]}
: @args
);
return $got_arrayref ? $args[0]
: join(' ', @args);
}
local/lib/perl5/Module/Build/Platform/Windows.pm view on Meta::CPAN
}
}
return join " ", @quoted;
}
sub split_like_shell {
# As it turns out, Windows command-parsing is very different from
# Unix command-parsing. Double-quotes mean different things,
# backslashes don't necessarily mean escapes, and so on. So we
# can't use Text::ParseWords::shellwords() to break a command string
# into words. The algorithm below was bashed out by Randy and Ken
# (mostly Randy), and there are a lot of regression tests, so we
# should feel free to adjust if desired.
(my $self, local $_) = @_;
return @$_ if defined() && ref() eq 'ARRAY';
my @argv;