Michael Lazzaro wrote:

So, to bring this thread back on track *again*, I hopefully offer this summary.


1) Damian's idea of using ~> and <~ as L2R and R2L is well-liked. Thus:

@out = grep { ... } map { ... } @in; # (1) (perl5)

becomes any of the following:

@out = grep { ... } <~ map { ... } <~ @in; # (2) (perl6)

@out <~ grep { ... } <~ map { ... } <~ @in; # (3)

@in ~> map { ... } ~> grep { ... } ~> @out; # (4)

My impression was that this was _instead_ of (1), eliminating the specialized syntax of the map, grep, etc. functions in favor of this more generic piping syntax, but that wasn't explicitly stated. Is that correct?
My impression was that ~> and <~ were more general than that, and mainly did syntax-rewriting.

So (4) above was translated in the parsing stage to be exactly identical to (1), by the following conversions:

# original (4)
@in ~> map { ... } ~> grep { ... } -> @out;

# Fully Parenthesized
(((@in ~> map { ... } ) ~> grep { ... } ) -> @out

# "@a ~> function " becomes " function @a
((map { ... } @in) ~> grep { ... } ) ~> @out

# @a ~> function ===> function @a
(grep { ... } (map { ... } @in)) ~> @out

# @a ~> @b ===> @b = @a
@out = (grep { ... } (map { ... } @in))

# removal of duplicate parenthesis
@out = grep { ... } map { ... } @in

So the syntax in (1) is still valid.

With (2) and (3), the situation is different, because they get syntax-converted into a different form:

# Original (3)
@out <~ grep { ... } <~ map { ... } <~ @in;

# fully parenthesized
@out <- ( grep { ... } <~ ( map { ... } <~ @in));

# function <~ @a ====> function :@a
@out <- { grep { ... } <- { map { ... } :@in ));

# function <~ @a =====> function :@a
@out <~ grep { ... } :(map { ... } :@in)

# @a <~ @b =====> @a = @b
@out = grep { ... } :(map { ... } :@in)

which is horrible, and no one would want to use that directly as opposed to syntax (1). But I can see beauty in (2) or (3).

Of course, since indirect-object syntax is syntactic sugar itself, this goes on to be:

# function :@a ===> @a.function, applied repeatedly
@out = @in.map({...}).grep({...});

which is yet another L2R syntax.

But it also implies that map(&block) and grep(&block) are methods on arrays (or Arrays).

The issue, as I see it, is that some people like to follow data flow from right to left through a chain of actions. Perl 5 supported this fine when it came to chained function calls:

sub byChar { $a cp $b }
for @words {
my $anagram = sort byChar split //, $_; # R2L flow of data.
push @$anagrams{$anagram}, $_;
}

Other people like to follow data flow from left to right through a chain of actions. Perl 5 supported this fine when it came to method invocations:

$emplyeeTable->select('unionized')->raiseSalary(0.05);

But if you needed to have a chain of function calls, you couldn't easily do left to right, and if you needed to have a chain of method invocations, you couldn't easily to right to left.

The one saving grace for method invocation was the use of "indirect object" syntax, which says that if the first argument of a multi-argument function is an object and is not followed by a comma, then the function should be interpreted as a method on that object:

print $filehandle $text;

is equivalent (in Perl 5) to

$filehandle->print($text);

But that doesn't scale. You can do the "block that evaluates to an object" trick to do some chaining, which gets you:

raiseSalary {select $employeeTable 'unionized'} 0.05;

But that is ugly as sin and not truely Right to Left; it's more "Middle to Out".

To summarize (and, Piers, you can quote me on this....)

Perl 5 allows you to do:

$object->meth1->meth2->meth3; # Perl5 chained method, L2R

Perl 6 will also allow you to do:

$data ~> sub1 ~> sub2 ~> sub3; # Perl6 chained subs, L2R

Perl 5 allows you to to:

sub3 sub2 sub1 $data; # Perl5 chained subs, R2L

Perl 6 will also allow you to do:

meth3 <~ meth2 <~ meth1 <~ $Xbject # Perl 6 chained methods, R2L

All four syntaxes will be available in Perl 6, modulo the fact that '->' is now spelled '.'

The additional functionality that when the last sub or method in the ~> and <~ is a variable an assigment is done is a convenience issue.


2) You might be able to combine L2R and R2L piping in one statement. Maybe.

(As an aside....

I almost wish that calling a method with an incomplete argument list would return a curried function, because that means that

$data ~> print <~ $filehandle;

would work!)






Reply via email to