]> git.vpit.fr Git - perl/modules/Scope-Upper.git/blobdiff - lib/Scope/Upper.pm
Implement yield()
[perl/modules/Scope-Upper.git] / lib / Scope / Upper.pm
index 5460c8378f3377f87a1869dba9fc7bcd24ebe348..ac254177da01cc448839ab2d38c3f6a8fcb5bd20 100644 (file)
@@ -9,13 +9,13 @@ Scope::Upper - Act on upper scopes.
 
 =head1 VERSION
 
 
 =head1 VERSION
 
-Version 0.18
+Version 0.19
 
 =cut
 
 our $VERSION;
 BEGIN {
 
 =cut
 
 our $VERSION;
 BEGIN {
- $VERSION = '0.18';
+ $VERSION = '0.19';
 }
 
 =head1 SYNOPSIS
 }
 
 =head1 SYNOPSIS
@@ -170,7 +170,7 @@ localize variables, array/hash values or deletions of elements in higher context
 
 =item *
 
 
 =item *
 
-return values immediately to an upper level with L</unwind>, and know which context was in use then with L</want_at> ;
+return values immediately to an upper level with L</unwind> and L</yield>, and know which context was in use then with L</want_at> ;
 
 =item *
 
 
 =item *
 
@@ -270,7 +270,10 @@ C<$key> is either an array index or a hash key, depending of which kind of varia
 
 If C<$what> is a string pointing to an undeclared variable, the variable will be vivified as soon as the localization occurs and emptied when it ends, although it will still exist in its glob.
 
 
 If C<$what> is a string pointing to an undeclared variable, the variable will be vivified as soon as the localization occurs and emptied when it ends, although it will still exist in its glob.
 
-=head2 C<localize_delete $what, $key, $context>
+=head2 C<localize_delete>
+
+    localize_delete $what, $key;
+    localize_delete $what, $key, $context;
 
 Introduces the deletion of a variable or an array/hash element delayed to the time of first return into the upper scope denoted by C<$context>.
 C<$what> can be:
 
 Introduces the deletion of a variable or an array/hash element delayed to the time of first return into the upper scope denoted by C<$context>.
 C<$what> can be:
@@ -295,10 +298,11 @@ C<$key> is ignored.
 
 =head2 C<unwind>
 
 
 =head2 C<unwind>
 
-    unwind @values;
+    unwind;
     unwind @values, $context;
 
     unwind @values, $context;
 
-Returns C<@values> I<from> the context pointed by C<$context>, i.e. from the subroutine, eval or format at or just above C<$context>, and immediately restart the program flow at this point - thus effectively returning to an upper scope.
+Returns C<@values> I<from> the subroutine, eval or format context pointed by or just above C<$context>, and immediately restart the program flow at this point - thus effectively returning C<@values> to an upper scope.
+If C<@values> is empty, then the C<$context> parameter is optional and defaults to the current context (making the call equivalent to a bare C<return;>) ; otherwise it is mandatory.
 
 The upper context isn't coerced onto C<@values>, which is hence always evaluated in list context.
 This means that
 
 The upper context isn't coerced onto C<@values>, which is hence always evaluated in list context.
 This means that
@@ -312,6 +316,30 @@ This means that
 will set C<$num> to C<'z'>.
 You can use L</want_at> to handle these cases.
 
 will set C<$num> to C<'z'>.
 You can use L</want_at> to handle these cases.
 
+=head2 C<yield>
+
+    yield;
+    yield @values, $context;
+
+Returns C<@values> I<from> the context pointed by or just above C<$context>, and immediately restart the program flow at this point.
+If C<@values> is empty, then the C<$context> parameter is optional and defaults to the current context ; otherwise it is mandatory.
+
+L</yield> differs from L</unwind> in that it can target I<any> upper scope (besides a C<s///e> substitution context) and not necessarily a sub, an eval or a format.
+Hence you can use it to return values from a C<do> or a C<map> block :
+
+    my $now = do {
+     local $@;
+     eval { require Time::HiRes } or yield time() => HERE;
+     Time::HiRes::time();
+    };
+
+    my @uniq = map {
+     yield if $seen{$_}++; # returns the empty list from the block
+     ...
+    } @things;
+
+Like for L</unwind>, the upper context isn't coerced onto C<@values>.
+
 =head2 C<want_at>
 
     my $want = want_at;
 =head2 C<want_at>
 
     my $want = want_at;
@@ -329,14 +357,13 @@ The previous example can then be "corrected" :
 
 will rightfully set C<$num> to C<26>.
 
 
 will rightfully set C<$num> to C<26>.
 
-=head2 C<uplevel $code, @args, $context>
+=head2 C<uplevel>
 
     my @ret = uplevel { ...; return @ret };
 
     my @ret = uplevel { ...; return @ret };
-    my @ret = uplevel { my @args = @_; ...; return @ret } @args;
-    my @ret = uplevel { ... } @args, $context;
+    my @ret = uplevel { my @args = @_; ...; return @ret } @args, $context;
     my @ret = &uplevel($callback, @args, $context);
 
     my @ret = &uplevel($callback, @args, $context);
 
-Executes the code reference C<$code> with arguments C<@args> as if it were located at the subroutine stack frame pointed by C<$context>, effectively fooling C<caller> and C<die> into believing that the call actually happened higher in the stack.
+Executes the code reference C<$callback> with arguments C<@args> as if it were located at the subroutine stack frame pointed by C<$context>, effectively fooling C<caller> and C<die> into believing that the call actually happened higher in the stack.
 The code is executed in the context of the C<uplevel> call, and what it returns is returned as-is by C<uplevel>.
 
     sub target {
 The code is executed in the context of the C<uplevel> call, and what it returns is returned as-is by C<uplevel>.
 
     sub target {
@@ -352,6 +379,8 @@ The code is executed in the context of the C<uplevel> call, and what it returns
     my @inverses = target(1, 2, 4); # @inverses contains (0, 0.5, 0.25)
     my $count    = target(1, 2, 4); # $count is 3
 
     my @inverses = target(1, 2, 4); # @inverses contains (0, 0.5, 0.25)
     my $count    = target(1, 2, 4); # $count is 3
 
+Note that if C<@args> is empty, then the C<$context> parameter is optional and defaults to the current context ; otherwise it is mandatory.
+
 L<Sub::Uplevel> also implements a pure-Perl version of C<uplevel>.
 Both are identical, with the following caveats :
 
 L<Sub::Uplevel> also implements a pure-Perl version of C<uplevel>.
 Both are identical, with the following caveats :
 
@@ -586,13 +615,14 @@ Where L</localize>, L</localize_elem> and L</localize_delete> act depending on t
     # $cxt = SCOPE(4), UP SUB UP SUB = UP SUB EVAL = UP CALLER(2) = TOP
     ...
 
     # $cxt = SCOPE(4), UP SUB UP SUB = UP SUB EVAL = UP CALLER(2) = TOP
     ...
 
-Where L</unwind>, L</want_at> and L</uplevel> point to depending on the C<$cxt>:
+Where L</unwind>, L</yield>, L</want_at> and L</uplevel> point to depending on the C<$cxt>:
 
     sub {
      eval {
       sub {
        {
 
     sub {
      eval {
       sub {
        {
-        unwind @things => $cxt;   # or uplevel { ... } $cxt;
+        unwind @things => $cxt;   # or yield @things => $cxt
+                                  # or uplevel { ... } $cxt
         ...
        }
        ...
         ...
        }
        ...
@@ -608,7 +638,7 @@ Where L</unwind>, L</want_at> and L</uplevel> point to depending on the C<$cxt>:
 
 =head1 EXPORT
 
 
 =head1 EXPORT
 
-The functions L</reap>, L</localize>, L</localize_elem>, L</localize_delete>,  L</unwind>, L</want_at> and L</uplevel> are only exported on request, either individually or by the tags C<':funcs'> and C<':all'>.
+The functions L</reap>, L</localize>, L</localize_elem>, L</localize_delete>,  L</unwind>, L</yield>, L</want_at> and L</uplevel> are only exported on request, either individually or by the tags C<':funcs'> and C<':all'>.
 
 The constant L</SU_THREADSAFE> is also only exported on request, individually or by the tags C<':consts'> and C<':all'>.
 
 
 The constant L</SU_THREADSAFE> is also only exported on request, individually or by the tags C<':consts'> and C<':all'>.
 
@@ -623,7 +653,8 @@ our %EXPORT_TAGS = (
  funcs  => [ qw<
   reap
   localize localize_elem localize_delete
  funcs  => [ qw<
   reap
   localize localize_elem localize_delete
-  unwind want_at
+  unwind yield
+  want_at
   uplevel
   uid validate_uid
  > ],
   uplevel
   uid validate_uid
  > ],