]> git.vpit.fr Git - perl/modules/Scope-Upper.git/blobdiff - README
This is 0.18
[perl/modules/Scope-Upper.git] / README
diff --git a/README b/README
index 3a5d76782328366d48bed86937fcd8cb843cd0d9..7d441b7558fa36830cac4af0e6297130b6b95c27 100644 (file)
--- a/README
+++ b/README
@@ -2,14 +2,17 @@ NAME
     Scope::Upper - Act on upper scopes.
 
 VERSION
-    Version 0.16
+    Version 0.18
 
 SYNOPSIS
     "reap", "localize", "localize_elem", "localize_delete" and "WORDS" :
 
         package Scope;
 
-        use Scope::Upper qw<reap localize localize_elem localize_delete :words>;
+        use Scope::Upper qw<
+         reap localize localize_elem localize_delete
+         :words
+        >;
 
         sub new {
          my ($class, $name) = @_;
@@ -51,22 +54,22 @@ SYNOPSIS
         package UserLand;
 
         {
-         Scope->new("top");      # initializes $UserLand::tag
+         Scope->new("top");    # initializes $UserLand::tag
 
          {
           Scope->catch;
-          my $one = 1 + undef;   # prints "top: Use of uninitialized value..."
+          my $one = 1 + undef; # prints "top: Use of uninitialized value..."
 
           {
            Scope->private;
            eval { require Cwd };
-           print $@;             # prints "Can't locate Cwd.pm in @INC (@INC contains:) at..."
-          }
+           print $@;           # prints "Can't locate Cwd.pm in @INC
+          }                    #         (@INC contains:) at..."
 
-          require Cwd;           # loads Cwd.pm
+          require Cwd;         # loads Cwd.pm
          }
 
-        }                        # prints "top: done"
+        }                      # prints "top: done"
 
     "unwind" and "want_at" :
 
@@ -113,6 +116,28 @@ SYNOPSIS
 
         target('hello'); # "hello from Uplevel::target()"
 
+    "uid" and "validate_uid" :
+
+        use Scope::Upper qw<uid validate_uid>;
+
+        my $uid;
+
+        {
+         $uid = uid();
+         {
+          if ($uid eq uid(UP)) { # yes
+           ...
+          }
+          if (validate_uid($uid)) { # yes
+           ...
+          }
+         }
+        }
+
+        if (validate_uid($uid)) { # no
+         ...
+        }
+
 DESCRIPTION
     This module lets you defer actions *at run-time* that will take place
     when the control flow returns into an upper scope. Currently, you can:
@@ -126,8 +151,10 @@ DESCRIPTION
     *   return values immediately to an upper level with "unwind", and know
         which context was in use then with "want_at" ;
 
-    *   execute a subroutine in the context of an upper subroutine stack
-        frame with "uplevel".
+    *   execute a subroutine in the setting of an upper subroutine stack
+        frame with "uplevel" ;
+
+    *   uniquely identify contextes with "uid" and "validate_uid".
 
 FUNCTIONS
     In all those functions, $context refers to the target scope.
@@ -274,15 +301,15 @@ FUNCTIONS
         }
 
         my @inverses = target(1, 2, 4); # @inverses contains (0, 0.5, 0.25)
-        my $count    = target(1, 2, 4); # $target is 3
+        my $count    = target(1, 2, 4); # $count is 3
 
     Sub::Uplevel also implements a pure-Perl version of "uplevel". Both are
     identical, with the following caveats :
 
     *   The Sub::Uplevel implementation of "uplevel" may execute a code
         reference in the context of any upper stack frame. The Scope::Upper
-        version only allows to uplevel to a subroutine stack frame, and will
-        croak if you try to target an "eval" or a format.
+        version can only uplevel to a subroutine stack frame, and will croak
+        if you try to target an "eval" or a format.
 
     *   Exceptions thrown from the code called by this version of "uplevel"
         will not be caught by "eval" blocks between the target frame and the
@@ -307,7 +334,7 @@ FUNCTIONS
         will print "inner block: wut..." with Sub::Uplevel and "outer block:
         wut..." with Scope::Upper.
 
-    *   Sub::Uplevel globally overrides "CORE::GLOBAL::caller", while
+    *   Sub::Uplevel globally overrides the Perl keyword "caller", while
         Scope::Upper does not.
 
     A simple wrapper lets you mimic the interface of "uplevel" in
@@ -325,6 +352,78 @@ FUNCTIONS
     Albeit the three exceptions listed above, it passes all the tests of
     Sub::Uplevel.
 
+  "uid $context"
+    Returns an unique identifier (UID) for the context (or dynamic scope)
+    pointed by $context, or for the current context if $context is omitted.
+    This UID will only be valid for the life time of the context it
+    represents, and another UID will be generated next time the same scope
+    is executed.
+
+        my $uid;
+
+        {
+         $uid = uid;
+         if ($uid eq uid()) { # yes, this is the same context
+          ...
+         }
+         {
+          if ($uid eq uid()) { # no, we are one scope below
+           ...
+          }
+          if ($uid eq uid(UP)) { # yes, UP points to the same scope as $uid
+           ...
+          }
+         }
+        }
+
+        # $uid is now invalid
+
+        {
+         if ($uid eq uid()) { # no, this is another block
+          ...
+         }
+        }
+
+    For example, each loop iteration gets its own UID :
+
+        my %uids;
+
+        for (1 .. 5) {
+         my $uid = uid;
+         $uids{$uid} = $_;
+        }
+
+        # %uids has 5 entries
+
+    The UIDs are not guaranteed to be numbers, so you must use the "eq"
+    operator to compare them.
+
+    To check whether a given UID is valid, you can use the "validate_uid"
+    function.
+
+  "validate_uid $uid"
+    Returns true if and only if $uid is the UID of a currently valid context
+    (that is, it designates a scope that is higher than the current one in
+    the call stack).
+
+        my $uid;
+
+        {
+         $uid = uid();
+         if (validate_uid($uid)) { # yes
+          ...
+         }
+         {
+          if (validate_uid($uid)) { # yes
+           ...
+          }
+         }
+        }
+
+        if (validate_uid($uid)) { # no
+         ...
+        }
+
 CONSTANTS
   "SU_THREADSAFE"
     True iff the module could have been built when thread-safety features.
@@ -375,13 +474,13 @@ WORDS
            {
             reap \&cleanup => $cxt;
             ...
-           }     # $cxt = SCOPE(0), or HERE
+           }     # $cxt = SCOPE(0) = HERE
            ...
-          }->(); # $cxt = SCOPE(1), or UP, or SUB, or CALLER, or CALLER(0)
+          }->(); # $cxt = SCOPE(1) = UP = SUB = CALLER(0)
           ...
-         };      # $cxt = SCOPE(2), or UP UP, or UP SUB, or EVAL, or CALLER(1)
+         };      # $cxt = SCOPE(2) = UP UP =  UP SUB = EVAL = CALLER(1)
          ...
-        }->();   # $cxt = SCOPE(3), or SUB UP SUB, or SUB EVAL, or CALLER(2)
+        }->();   # $cxt = SCOPE(3) = SUB UP SUB = SUB EVAL = CALLER(2)
         ...
 
     Where "localize", "localize_elem" and "localize_delete" act depending on
@@ -392,19 +491,19 @@ WORDS
           sub {
            {
             localize '$x' => 1 => $cxt;
-            # $cxt = SCOPE(0), or HERE
+            # $cxt = SCOPE(0) = HERE
             ...
            }
-           # $cxt = SCOPE(1), or UP, or SUB, or CALLER, or CALLER(0)
+           # $cxt = SCOPE(1) = UP = SUB = CALLER(0)
            ...
           }->();
-          # $cxt = SCOPE(2), or UP UP, or UP SUB, or EVAL, or CALLER(1)
+          # $cxt = SCOPE(2) = UP UP = UP SUB = EVAL = CALLER(1)
           ...
          };
-         # $cxt = SCOPE(3), or SUB UP SUB, or SUB EVAL, or CALLER(2)
+         # $cxt = SCOPE(3) = SUB UP SUB = SUB EVAL = CALLER(2)
          ...
         }->();
-        # $cxt = SCOPE(4), UP SUB UP SUB, or UP SUB EVAL, or UP CALLER(2), or TOP
+        # $cxt = SCOPE(4), UP SUB UP SUB = UP SUB EVAL = UP CALLER(2) = TOP
         ...
 
     Where "unwind", "want_at" and "uplevel" point to depending on the $cxt:
@@ -413,19 +512,19 @@ WORDS
          eval {
           sub {
            {
-            unwind @things => $cxt;     # or uplevel { ... } $cxt;
+            unwind @things => $cxt;   # or uplevel { ... } $cxt;
             ...
            }
            ...
-          }->(); # $cxt = SCOPE(0 .. 1), or HERE, or UP, or SUB, or CALLER(0)
+          }->(); # $cxt = SCOPE(0) = SCOPE(1) = HERE = UP = SUB = CALLER(0)
           ...
-         };      # $cxt = SCOPE(2), or UP UP, or UP SUB, or EVAL, or CALLER(1) (*)
+         };      # $cxt = SCOPE(2) = UP UP = UP SUB = EVAL = CALLER(1) (*)
          ...
-        }->();   # $cxt = SCOPE(3), or SUB UP SUB, or SUB EVAL, or CALLER(2)
+        }->();   # $cxt = SCOPE(3) = SUB UP SUB = SUB EVAL = CALLER(2)
         ...
 
         # (*) Note that uplevel() will croak if you pass that scope frame,
-        #     because it can't target eval scopes.
+        #     because it cannot target eval scopes.
 
 EXPORT
     The functions "reap", "localize", "localize_elem", "localize_delete",
@@ -472,6 +571,28 @@ CAVEATS
     may help to use a perl higher than 5.8.9 or 5.10.0, as they contain some
     context-related fixes.
 
+    Calling "goto" to replace an "uplevel"'d code frame does not work :
+
+    *   for a "perl" older than the 5.8 series ;
+
+    *   for a "DEBUGGING" "perl" run with debugging flags set (as in "perl
+        -D ...") ;
+
+    *   when the runloop callback is replaced by another module.
+
+    In those three cases, "uplevel" will look for a "goto &sub" statement in
+    its callback and, if there is one, throw an exception before executing
+    the code.
+
+    Moreover, in order to handle "goto" statements properly, "uplevel"
+    currently has to suffer a run-time overhead proportional to the size of
+    the the callback in every case (with a small ratio), and proportional to
+    the size of all the code executed as the result of the "uplevel" call
+    (including subroutine calls inside the callback) when a "goto" statement
+    is found in the "uplevel" callback. Despite this shortcoming, this XS
+    version of "uplevel" should still run way faster than the pure-Perl
+    version from Sub::Uplevel.
+
 DEPENDENCIES
     XSLoader (standard since perl 5.006).
 
@@ -480,6 +601,8 @@ SEE ALSO
 
     Alias, Hook::Scope, Scope::Guard, Guard.
 
+    Sub::Uplevel.
+
     Continuation::Escape is a thin wrapper around Scope::Upper that gives
     you a continuation passing style interface to "unwind". It's easier to
     use, but it requires you to have control over the scope where you want
@@ -487,8 +610,6 @@ SEE ALSO
 
     Scope::Escape.
 
-    Sub::Uplevel provides a pure-Perl implementation of "uplevel".
-
 AUTHOR
     Vincent Pit, "<perl at profvince.com>", <http://www.profvince.com>.