Author: larry
Date: Mon Mar 12 16:10:26 2007
New Revision: 14343
Modified:
doc/trunk/design/syn/S06.pod
Log:
Added the KitchenSink role.
Fiddle the feed operators to work better with files and such.
Modified: doc/trunk/design/syn/S06.pod
==============================================================================
--- doc/trunk/design/syn/S06.pod (original)
+++ doc/trunk/design/syn/S06.pod Mon Mar 12 16:10:26 2007
@@ -15,7 +15,7 @@
Date: 21 Mar 2003
Last Modified: 12 Mar 2007
Number: 6
- Version: 78
+ Version: 79
This document summarizes Apocalypse 6, which covers subroutines and the
@@ -886,39 +886,18 @@
Because feeds are defined as lazy pipes, a chain of feeds may not begin
and end with the same array without some kind of eager sequence point.
-That is, this doesn't work:
+That is, this isn't guaranteed to work:
- my @data = 1,2,3;
@data <== grep { $_ % 2 } <== @data;
-but this does:
+either of these do:
- my @data = 1,2,3;
- my @tmp = eager @data;
- @data <== grep { $_ % 2 } <== @tmp;
-
-(But note: feed operators have push semantics when the receiver is an array.
-Use assignment to get clear-first semantics.)
-
-Conjecture: the following are possible, but only if we are very careful
-to cut loose the old @data on the blunt end of the pipe before rebinding
-the pointy end:
+ @data <== grep { $_ % 2 } <== eager @data;
+ @data <== eager grep { $_ % 2 } <== @data;
- @data <== grep { $_ % 2 } <== @data;
- @data := do { grep { $_ % 2 } <== @data; }
-
-And this would need to force an "eager" evaluation to a temporary
-list to work at all:
-
- @data = do { grep { $_ % 2 } <== @data; }
-
-Otherwise it's the equivalent of the Unix newbie mistake:
-
- filter foo >foo
-
-Arguably we could take the Unix approach and force the newbie to just
-learn to deal with it explicitly. (Arguably this could also be construed
-as antisocial.)
+Conjecture: if the cloning process eagerly duplicates C<@data>, it could
+be forced to work. Not clear if this is desirable, since ordinary clones
+just clone the container, not the value.
Leftward feeds are a convenient way of explicitly indicating the typical
right-to-left flow of data through a chain of operations:
@@ -942,8 +921,22 @@
level. (Parens would also work, since a "do" is assumed there.)
If the operand on the sharp end of a feed is not a call to a variadic
-operation, it must be something else that can be interpreted as a
-list receiver.
+operation, it must be something else that can be interpreted as a list
+receiver, or a scalar expression that can be evaluated to produce an
+object that does the C<KitchenSink> role, such as an C<IO> object.
+Such an object provides C<.clear> and C<.push> methods that will
+be called as appropriate to send data. (Note that an C<IO> object
+used as a sink will force eager evaluation on its pipeline, so the
+next statement is guaranteed not to run till the file is closed.
+In contrast, an C<Array> object used as a sink turns into a lazy
+array.)
+
+Any non-variadic object (such as an C<Array> or C<IO> object) used as a filter
+between two feeds is treated specially as a I<tap> that merely captures
+data I<en passant>. You can safely install such a tap in an extended pipeline
+without changing the semantics. An C<IO> object used as a tap does not
+force eager evaluation since the eagerness is controlled instead by the
+downstream feed.
Any prefix list operator is considered a variadic operation, so ordinarily
a list operator adds any feed input to the end of its list.
@@ -954,6 +947,12 @@
foo() ==> say @(*), " is what I meant";
bar() ==> @@(*).baz();
+Likewise, an C<Array> used as a tap may be distinguished from an C<Array> used
+as a translation function:
+
+ numbers() ==> @array ==> bar() # tap
+ numbers() ==> @array[@(*)] ==> bar() # translation
+
Feeding into the C<*> "whatever" term sets the source for the next sink.
To append multiple sources to the next sink, double the angle: