Skip to content

Commit

Permalink
gather/take user-vs-library considerations
Browse files Browse the repository at this point in the history
Incorporate feedback from awwaiid++, PerlJam++, sorear++.
  • Loading branch information
TimToady committed Jun 23, 2011
1 parent b4e7bc1 commit d5e7386
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions S04-control.pod
Original file line number Diff line number Diff line change
Expand Up @@ -700,14 +700,30 @@ X<gather>X<take>
A variant of C<do> is C<gather>. Like C<do>, it is followed by a statement
or block, and executes it once. Unlike C<do>, it evaluates the statement or
block in sink (void) context; its return value is instead specified by calling
the C<take> list prefix operator one or more times within the dynamic scope of
the C<take> list prefix operator one or more times within the scope (either lexical or dynamic) of
the C<gather>. The C<take> function's signature is like that of C<return>;
while having the syntax of a list operator, it merely returns a single item
or "argument" (see L<S02> for definition). The C<take> function is lexotic
if there is a visible outer C<gather>, but falls back to purely dynamic if not.
(Use of the dynamic semantics cannot be guaranteed to be portable when passing
closures into some other construct, either built-in or not, since implementations
of libraries and of Perl itself may use C<gather>/C<take> internally.)
or "argument" (see L<S02> for definition).

The C<take> function is lexotic if there is a visible outer C<gather>,
but falls back to purely dynamic if not. Well, it doesn't really
fall back, since a C<take> knows at compile time whether it is being
used lexically or dynamically. Less obviously, so does a C<gather>;
if a C<gather> lexically contains any C<take> calls, it is marked as
lexotic-only, and it will be invisible to a dynamic C<take>. If the
C<gather> contains no C<take> lexically, it by definition cannot be
the lexotic target of any C<take>, so it can only harvest dynamic
C<take> calls. The only remaining difficulty arises if both the user
and a library writer attempt to use dynamic gather with user-defined
callbacks that contain C<take>. So we will say that it is erroneous
for a library writer to mix dynamic gather with callbacks unless
those callbacks are somehow "ungathered" to the outer dynamic scope.
[Conjecture: there should either be an C<callergather> primitive that
does this, or it should be added to the job description of C<lift>.
A third option is to allow labeled C<gather>/C<take> for such a situation,
and dynamic C<take> must match the C<gather>'s label (or lack thereof) exactly.
(Using the term "label" loosely, to include other solutions besides the label syntax,
such as .gather and .take methods on some identity object.)]

If you take multiple items in a comma list (since it is, after all, a list
operator), they will be wrapped up in a C<Parcel> object for return as the
Expand Down

0 comments on commit d5e7386

Please sign in to comment.