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: