Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-23 Thread arcadi shehter
Thomas A. Boyer writes:
  Michael Lazzaro wrote:
   *Now*, what to do about the fantastic magic that pointy-sub provides?
   The _spectacular_ win would be if we could just recognize an optional
   parameter list as part of a block.
   
map @a : ($a,$b) {...}  # params + closure = closure with params?
for @a : ($a,$b) {...}
   
   So that anywhere you had a closure, you could put a paramlist in front
   of it.  Not likely we could get that to work, since best-case scenario
   it would probably barf on $a and $b being undefined before it ever got
   to the closure.  But it might be possible, at the expense of some
   parser complexity.
  

I sertainly can do it like taht : 
   map @a :  {...}  is sig($a,$b) 
   for @a :  {...}  is sig($a,$b) 

or 

  map @a :  sub($a,$b) {...} 
  for @a :  sub($a,$b) {...} 

or 

  @a ~ map sub($a,$b) {...} 

It also seems that the difference between map and for may be twisted
as follows : map apply particular closure to several ( possibly one )
array , while for takes particular array ( which may have possibly
passed some pre -zipping/-weaving) and apply pour it to several (
possibly one ) closures.  

if we assume that for can accept as its last arguments sequence one or
more closures than with the existing pointy sub meaning of - we can
have 

for @a - ( $x ){ ... } 
   - ( $y ){ ... } 
   - ( $z ){ ... } ;

and , is unnecessary after the curly for the same reason it is
unnecessary after @a. 

since grep/map/and_friends are just subroutines this naturally gives
piping behaviour : 


for @a   - ( $x ){ ... }   #this is map 
   ,grep - ( $y ){ ... }   #this is grep
   ,sort - ( $a,$b ){ ... } ;  #this is sort 

this is similar to the old then suggestion of Damian Conway 

@a then map  - ( $x ){ ... }   #this is map 
   then grep - ( $y ){ ... }   #this is grep
   then sort - ( $a,$b ){ ... } ;  #this is sort 


arcadi 





Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-23 Thread Michael Lazzaro

On Wednesday, January 22, 2003, at 11:42  AM, Kwindla Hultman Kramer 
wrote:
Michael Lazzaro writes:


And it provides a very visual way to define any pipe-like algorithm, 
in
either direction:

$in - lex - parse - codify - optimize - $out;   # L2R

$out - optimize - codify - parse - lex - $in;   # R2L

It's clear, from looking at either of those, that they represent data
pipes.  Both are even clearer than the equiv:

$out = $in.lex.parse.codify.optimize;
snip

One question: How does this approach to building a pipe-lining syntax
square with the alternative spelling of the assignment operator
feature that's been discussed elsewhere in this thread? It's not
immediately obvious to me how the post-/pre-invocant operation
becomes an assignment at the end of the chain. In other words, are
the first two code fragments above really equivalent to the third?


They're equiv only if make a rule saying they're equiv, like what 
Damian was proposing for ~ and ~.  (Except this isn't quite the same 
thing as Damian was proposing, which is why I'm not using ~ and ~ to 
describe it.)

You could for example use:

$x - 5;

...to do assignment (if you're into that sort of thing) if the '-' was 
overloaded to do the right thing when it was piping 'to' a simple 
variable.  Even

$x - $y - 5;

could work, since the R2L chain would do the same as $x = $y = 5;

So short answer, it squares pretty well with an alternative spelling 
for assignment, for persons that would like to do that.  They'd be 
equiv iff we defined the operators such that they were.

MikeL



Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Dave Whipp
Michael Lazzaro [EMAIL PROTECTED] wrote in message
[EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
 Of course, _I'd_ even prefer using - and - as the 'piping' operators,
 and having ~ or | for pointy sub, because then $a-foo and $a.foo
 really _could_ be the same thing, 'cept for precedence.  But that's not
 gonna happen, and _I'm_ not gonna press it.  :-)

I wouldn't (and don't) give up so easily! The - syntax for anonymous
subs is cute: but it seems to be cute only in limited contexts -- those
where it is also being used as a (conceptual) piping operator.
Compare:

 $a = sub ($a, $b) { ... }
 $x = - ($y, $z) { ... }

The pointy-arrow doesn't buy anything here.

But in a for loop:

 for 1,2,3,4 { ... }
 for 1,2,3,4 - ($a,$b) {...}

its cuteness works because the brain sees it as a piping operator (even
though its not).

Perl6 is still Perl. We're allowed to do a bit of DWIMery in the parser,
if needed, to make the simple (common) cases work. So perhaps we
should define the Cfor in terms of pipelines. With some minor
syntax changes, we can free up the - operator:

  for 1,2,3,4 ~ sub ($a,$b) { ... }

Sure, its not quite so cute. You could rename the Csub if desired
(for example, perhaps it could be spelt Cmy in this context, though
you'd need to work on the lexical scoping rules). The only remaining
magic would be to retrofit the basic Cfor to work.

And then we can replace the ~ with -:

 for 1,2,3,4
- sub ($a, $b) { $a+$b }
- sub ($a) { $a**2 }
- { $^foo - 1 }
- print;

And this begs the question: what exactly does the Cfor contribute to
the semantics of the pipeline? What would Cmap (in void context)
do differently?


Dave.





Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread David Storrs
On Tue, Jan 21, 2003 at 03:52:30PM -0800, Dave Whipp wrote:

  $a = sub ($a, $b) { ... }
  $x = - ($y, $z) { ... }
 
 The pointy-arrow doesn't buy anything here.

IMHO, it's actually a loss.  I have yet to come up with any mnemonic
for pointy arrow means sub that will actually stick in my brain.
Every time I see this construct, I have to stop in my tracks and
mentally flip through the reference manual.


 But in a for loop:
 
  for 1,2,3,4 { ... }
  for 1,2,3,4 - ($a,$b) {...}
 
 its cuteness works because the brain sees it as a piping operator (even
 though its not).

Agreed.


[snip]
 And then we can replace the ~ with -:
 
  for 1,2,3,4
 - sub ($a, $b) { $a+$b }
 - sub ($a) { $a**2 }
 - { $^foo - 1 }
 - print;
 
 And this begs the question: what exactly does the Cfor contribute to
 the semantics of the pipeline? What would Cmap (in void context)
 do differently?

One potential answer: make 'map' be lazy by default and 'for' be
nonlazy (energetic? active? ADHD?).  My logic in suggesting it this
way around is that, to me, 'for' seems to operate more on a whole
list, while 'map' is intended to operate on elements one after
another.  Like so:

for (1,2,3) { print }  # I want to call print for this whole list
map { print } (1,2,3)  # Map the 'print' function over the elements
   #  of this list


--Dks



Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Dave Whipp

David Storrs [EMAIL PROTECTED] wrote in message
[EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
  And then we can replace the ~ with -:
 
   for 1,2,3,4
  - sub ($a, $b) { $a+$b }
  - sub ($a) { $a**2 }
  - { $^foo - 1 }
  - print;
 
  And this begs the question: what exactly does the Cfor contribute to
  the semantics of the pipeline? What would Cmap (in void context)
  do differently?

 One potential answer: make 'map' be lazy by default and 'for' be
 nonlazy (energetic? active? ADHD?).  My logic in suggesting it this
 way around is that, to me, 'for' seems to operate more on a whole
 list, while 'map' is intended to operate on elements one after
 another.  Like so:

 for (1,2,3) { print }  # I want to call print for this whole list
 map { print } (1,2,3)  # Map the 'print' function over the elements
#  of this list

I have a feeling its the other way round:

  (1,2,3,4) ~ map { print }
Vs
  for 1,2,3,4 - print

The obj ~ method args form calls the method on the object. Cmap
is then a method (called on the entire list) that calls its codeblock for
each member

The for list - sub would call the sub for each member of the list. Hence
an equivalence:

 for list - { per-elem code }
eq
 list ~ map { per-elem code }

But remember, this is all getting very hypothetical: - doesn't (currently)
mean L2R pipe into sub

Dave.






Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Michael Lazzaro

On Tuesday, January 21, 2003, at 03:52  PM, Dave Whipp wrote:

But in a for loop:

 for 1,2,3,4 { ... }
 for 1,2,3,4 - ($a,$b) {...}

its cuteness works because the brain sees it as a piping operator (even
though its not).


That's an excellent observation.  I like the 'for' syntax quite a bit, 
but never quite could put my finger on why it worked so well.  You're 
right, that's exactly it.

And this begs the question: what exactly does the Cfor contribute to
the semantics of the pipeline? What would Cmap (in void context)
do differently?


Hmm.  Perhaps there doesn't _need_ to be a difference.  You currently 
use Cfor when you don't care about capturing the results.  You use 
Cmap when you do.  But since we can identify context, perhaps they 
could be synonyms, if we tweak things a little.

*** SPECULATION AHEAD ***

Note that Cfor allows you to name the arguments, using the pointy sub 
rule:

for @a - ($a,$b) {...}

but note ALSO that it'd be great if Cmap and friends had that 
capability, so you could Cmap two-at-a-time, etc.  (Cgrep and 
Csort don't really need it, but I *suppose* you could use it for 
grepping/sorting tuples.)

So we want the pointy-sub rule for Cmap and friends too:

my @a = map - ($a,$b) {...};   # pass to {...} 2-at-a-time, as $a 
and $b

Pretty neat.

But ignoring pointy-sub for the moment, and assuming that we in fact 
used - and - to mean pre/post-invocant (e.g. pipes): if we defined 
Cfor as just another word for Cmap, what we really want is rules 
such that *all* of the following work.  Question is, is it possible to 
come up with something consistent.  Maybe.

# void context

@a.map {...}
@a.for {...}  # identical
@a - map {...}   # identical
@a - for {...}   # identical

@a - {...}   # identical (a cool shorthand when given 
a closure?)

for @a {...}  # Doh! This wouldn't work
for @a : {...}# Hey, but this would (indirect object 
syntax)
map @a : {...}# identical

for @a,@b,@c : {...}  # is this OK?
for (@a,@b,@c) : {...}# OK, and better looking

# list context

my @a = @b - for {...}
my @a = @b - map {...} # identical
my @a = map {...} - @b # identical
my @a = for {...} - @b # identical

my @a - map {...} - @b# identical
my @a - for {...} - @b# identical

That works.  Pretty darn well, too.  (Note the critical bit, the 
introduction of indirect object syntax to Cfor.)

*Now*, what to do about the fantastic magic that pointy-sub provides?  
The _spectacular_ win would be if we could just recognize an optional 
parameter list as part of a block.

map @a : ($a,$b) {...}  # params + closure = closure with params?
for @a : ($a,$b) {...}

So that anywhere you had a closure, you could put a paramlist in front 
of it.  Not likely we could get that to work, since best-case scenario 
it would probably barf on $a and $b being undefined before it ever got 
to the closure.  But it might be possible, at the expense of some 
parser complexity.

If we couldn't do that, you would have to say:

for @a : sub ($a,$b) {...}   # OK
or
@a - for sub ($a,$b) {...}  # a bit icky

The first of those looks better than the second.  I loathed the second 
after I first wrote it, but now it's beginning to grow on me a bit 
better.  The intent is certainly clear, for example.

The pointy-sub syntax doesn't really work in these cases, though.  I 
can't think of anything you could use in place of 'sub' that would make 
either of those look better.

So, the benefits of trying to pursue this:  It makes Cfor and Cmap 
synonyms, and gives each the magical powers of the other.  The fact 
even Cfor is now an object method means you could say:

   for @obj : {...}

and even overload the Cfor behavior for a Collection-based @obj.  It 
also gets rid of the perl5 bugaboo:

   for (@a) {...}
   map {...} @a;# params are reversed.  Newbie trap!

So the biggest single trick is, Cfor would have the colon after the 
list:

   for @a : {...}

If we did that, the rest might just work.

Anyway, just speculation.

MikeL



Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Luke Palmer
 Date: Wed, 22 Jan 2003 10:38:23 -0800
 From: Michael Lazzaro [EMAIL PROTECTED]
 
 On Tuesday, January 21, 2003, at 03:52  PM, Dave Whipp wrote:
  But in a for loop:
 
   for 1,2,3,4 { ... }
   for 1,2,3,4 - ($a,$b) {...}
 
  its cuteness works because the brain sees it as a piping operator (even
  though its not).
 
 *** SPECULATION AHEAD ***
 
 Note that Cfor allows you to name the arguments, using the pointy sub 
 rule:
 
  for @a - ($a,$b) {...}
 
 but note ALSO that it'd be great if Cmap and friends had that 
 capability, so you could Cmap two-at-a-time, etc.  (Cgrep and 
 Csort don't really need it, but I *suppose* you could use it for 
 grepping/sorting tuples.)

I'm not sure whether you know that this already is the plan.  The
following three are equivalent:

  my @a = map { uc } @b;
  my @a = map { uc $^a } @b;
  my @a = map - $x { uc $x } @b;

And I believe two-at-a-time would also work.

 So we want the pointy-sub rule for Cmap and friends too:
 
  my @a = map - ($a,$b) {...};   # pass to {...} 2-at-a-time, as $a 
 and $b
 
 Pretty neat.
 
 But ignoring pointy-sub for the moment, and assuming that we in fact 
 used - and - to mean pre/post-invocant (e.g. pipes): if we defined 
 Cfor as just another word for Cmap, what we really want is rules 
 such that *all* of the following work.  Question is, is it possible to 
 come up with something consistent.  Maybe.
 
  # void context
 
  @a.map {...}
  @a.for {...}  # identical
  @a - map {...}   # identical
  @a - for {...}   # identical
 
  @a - {...}   # identical (a cool shorthand when given 
 a closure?)
 
  for @a {...}  # Doh! This wouldn't work
  for @a : {...}# Hey, but this would (indirect object 
 syntax)
  map @a : {...}# identical
 
  for @a,@b,@c : {...}  # is this OK?
  for (@a,@b,@c) : {...}# OK, and better looking
 
  # list context
 
  my @a = @b - for {...}
  my @a = @b - map {...} # identical
  my @a = map {...} - @b # identical
  my @a = for {...} - @b # identical
 
  my @a - map {...} - @b# identical
  my @a - for {...} - @b# identical
 
 That works.  Pretty darn well, too.  (Note the critical bit, the 
 introduction of indirect object syntax to Cfor.)

Yeah, good point.  Why is it that Cfor and Cmap, so similar in
nature, accept such different forms for their arguments?

But, I'll have to admit,

  for @a,@b :- $a, $b { ... }

Doesn't look quite as nice as the older version :-

I'm thinking it would be a very good idea to unify Cfor and Cmap
in their argument style.  I still think the distinction between
Cfor's void and Cmap's list context is a good one; i.e. don't make
them Ientire synonyms.

But it seems natural to have Cfor a method of CArray, however
unnatural that seems.  I don't know, my thoughts are quite unclear at
this point; perhaps I'll write back when I've thought about this a bit
more.

Luke



Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Kwindla Hultman Kramer

Michael Lazzaro writes:

  And it provides a very visual way to define any pipe-like algorithm, in 
  either direction:
  
  $in - lex - parse - codify - optimize - $out;   # L2R
  
  $out - optimize - codify - parse - lex - $in;   # R2L
  
  It's clear, from looking at either of those, that they represent data 
  pipes.  Both are even clearer than the equiv:
  
  $out = $in.lex.parse.codify.optimize;
  
  Whether you would code a pipeline as L2R or R2L depends on the specific 
  algorithm you're representing, and is purely a matter of taste...  
  you'd probably use R2L in the same places as you use Cmap-like 
  chaining in Perl5.  I can't begin to justify why one should be superior 
  to the other, and would certainly use them both.
  

This explanation of (and rationale for) a post-invocant underpinning
for l2r/r2l pipe-lining was wonderfully clear. I've also found that
newish perl programmers frequently find Cmap and friends to be
confusing, particularly when they are traveling in a pack (not to
speak of an Cunpack).

One question: How does this approach to building a pipe-lining syntax
square with the alternative spelling of the assignment operator
feature that's been discussed elsewhere in this thread? It's not
immediately obvious to me how the post-/pre-invocant operation
becomes an assignment at the end of the chain. In other words, are
the first two code fragments above really equivalent to the third?

Kwin




Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Austin Hastings

--- Luke Palmer [EMAIL PROTECTED] wrote:
[[... Massive elision ...]]

 I'm thinking it would be a very good idea to unify Cfor and Cmap
 in their argument style.  I still think the distinction between
 Cfor's void and Cmap's list context is a good one; i.e. don't
 make them Ientire synonyms.
 
 But it seems natural to have Cfor a method of CArray, however
 unnatural that seems.  I don't know, my thoughts are quite unclear at
 this point; perhaps I'll write back when I've thought about this a
 bit more.

On a somewhat disjunctive note, if you're going to play games with
unifying Cfor and Cmap, let's undef the operation-order of map.

That is, 

for (1,2,3) { print }
# 1 2 3

map { print } (1, 2, 3) # or however you rewrite the syntax
# ? ? ?

@a = map { print } (1, 2, 3)
for @a { print }
# 1 2 3

Note that the order of the results of map would still be guaranteed,
but not the order of operation. This is for threading, obviously, and
we should probably do the same thing everywhere we can, so that if you
want serial operation, you use for or some construction that honors
ordering attributes internal to the data.

The point is to warn people that preserving state in map blocks won't
work, although stateless data or statistics will:

map { count++; ... } @array # works fine -- count == array.length 
map { %hist{$_}++ } @array  # works fine -- hist{} counts occurrences

map { ...$last ...; # I do not think that code
  last=$_; ... } @array # means what you think it means...


=Austin




Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-22 Thread Thomas A. Boyer
Michael Lazzaro wrote:
 *Now*, what to do about the fantastic magic that pointy-sub provides?
 The _spectacular_ win would be if we could just recognize an optional
 parameter list as part of a block.
 
  map @a : ($a,$b) {...}  # params + closure = closure with params?
  for @a : ($a,$b) {...}
 
 So that anywhere you had a closure, you could put a paramlist in front
 of it.  Not likely we could get that to work, since best-case scenario
 it would probably barf on $a and $b being undefined before it ever got
 to the closure.  But it might be possible, at the expense of some
 parser complexity.

I agree that it might be difficult to recognize the ($a,$b) as a parameter list rather 
than a list expression. Smalltalk marks block parameters this way:

   b := [:a :b | a  b].  Assign a two-paremeter block to b
   ^b value: 1 value: 2.  Return the value of invoking b on 1 and 2


The [ makes it clear that a block is next; the : marks parameters and the | ends 
the list. A literal translation to Perlish syntax would be

  map @a { :$a :$b | $a + $b }

but then we get into discussions about Larry's 2nd law of colons. Besides, we perl 
mongers already use | for a sufficient multitude of other things. 
But my point is: just because C-ish programmers think (...){ ... } feels 
parameterish doesn't mean that the parameter declaration has to come *before* the 
opening curly brace. And no, despite two Smalltalk-related posts in the last three 
days, I don't want to turn Perl into Smalltalk; I just think that Smalltalk has a nice 
syntactic solution to the problem we're talking about here.

The problem is, I can't think of any syntaxes better than

  map @a { $a $b:   $a + $b }  # hey, buddy, can you lend me a colon?
  map @a { args $a, $b; $a + $b }
  map @a { - ($a, $b); $a + $b }
  map @a { $a, $b -$a + $b }  # can't coexist with A4-style pointy subs
  map @a { my^ $a, $b;  $a + $b }  # the ^ is reminiscent of map @a { $^a + $^b }
  map @a {{$a, $b}  $a + $b }  # all other uses of consecutive curlies require 
space: { {
  map @a { EXPLICIT_ARGUMENTS_TO_FOLLOW $a $b ARGUMENTS_STOP_HERE $a + $b }

and they all look uglier than... well, um, uh... I want.

I have a strong suspicion that this possibility was carefully considered by {LW, DC, 
...} (that's set notation, not a code block :) before the Apocalypse 4 pointy sub 
syntax (and the for-loop syntax using it) was promulgated. And that it was rejected 
because it's hard to come up with something that looks right. Even the Smalltalk 
syntax is a tad awkward-looking to me, and the warpage that is necessary to make it 
Perlish just compounds the problem.

Hmmm. I guess I didn't really say anything here, did I?  Do I post these ruminations, 
or should I just hit that cancel button before I open my mouth and remove all doubt?

Nah. I'm goin' for it: maybe somebody else will think of a syntax that looks right!

=thom
Must be a yearning deep in human heart to stop other people from doing as they 
please. Rules, laws--always for the other fellow. A murky part of us, something we had 
before we came down out of the trees, and failed to shuck when we stood up. Because 
not one of those people said: 'Please pass this so I won't be able to do something I 
know I should stop.' Nyet, tovarishchee, was always something they hated to see their 
neighbors doing. Stop them 'for their own good'--not because the speaker claimed to be 
harmed by it. 
Manuel Davis O'Kelley 
The Moon is a Harsh Mistress




Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-21 Thread Michael Lazzaro

On Monday, January 20, 2003, at 04:33  PM, Michael Lazzaro wrote:

But both the OO and pipeline syntaxes do more to point out the noun, 
verb, and adjective of the operation.
  

Adverb.  The {...} part is an adverb, not an adjective.  Sorry there.

MikeL




Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-21 Thread Smylers
Michael Lazzaro wrote:

  On Monday, January 20, 2003, at 12:30  PM, Smylers wrote:
 
  It was only on reading that (and discovering that you hadn't
  previously known about the 'optional comma with closure argument'
  rule) that I understood why you had previously been so in favour of
  proposed new syntaxes: through a desire to banish the Perl 5 syntax.
  
 Yes.  Again, it's not that I never knew about the perl5 rule,

Sorry, I wasn't meaning to suggest that you didn't know Perl 5; I was
specifically referring to your saying that you'd presumed that
conditions and loops were special cases in the grammar, but that
actually they'll be dealt with by the general Perl _6_ rule about commas
and closure arguments.

 it's that I _dislike_ the perl5 rule, ...

Oh.  That's dislike rather than disliked?  My question was
predicated on your declaration I emphatically withdraw my objection,
which I took to mean that your knowledge of the infrared comma rule --
or whatever it's called -- meant you no longer disliked the Perl 5
syntax?

 as I dislike most special-case grammar rules.

So do I!  I was particularly impressed by the ultraviolet comma rule,
and how it avoids special cases, when Damian paraded it at a talk last
summer.

I also don't reckon it's _that_ special.  So long as the rule is that
such commas are optional, as distinct from their absence being
mandatory, then the rule is a very general one: commas may be omitted
where they aren't needed to delimit list items.  Obviously with string
and numeric values commas are always required:

  $a -1

They are the only way of determining op/term for the minus sign: a
single argument of one less than the value in C$a, or two arguments
with the second being minus one?

But closures can be unambiguously determined without commas.  Since
whitespace is no longer allowed in hash look-ups, space followed by an
open brace must be the start of a closure, and hence another argument.
Similarly once the closing brace has been reached the closure is ...
ahem, closed, so anything following must be a separate argument.

 If we dropped Cmap, etc., we could drop the inferred-comma rule as
 well (unless we're really successful in making Cif a simple
 function, in which case we need the rule anyway, so who cares?)

I guess that's the crucial issue.  Since it was Damian saying that it is
possible to have Cif and friends as functions -- and since this was
something that'd already been dealt with before I joined this list, and
so presumably would've had any impossibility pointed out -- I believed
it to be true.

There's another sub-thread casting doubt on -- and trying to resolve --
the issue.  I completely agree that whether the infrared comma rule is
needed over there makes a big difference to its use here.

But I think I disagree about the who cares part ...

 But the inferred-comma rule is tangential to my dislike of the current
 Cmap syntax.  I'd dislike Cmap, and like pipelines, even if the
 inferred-comma rule wasn't there.

As you've not doubt noticed, I'm the opposite: I like Cmap and don't
(yet?) see the point of right-left pipelines.  (That means not that I
claim you're in some way 'wrong' to have those preferences, merely that
we think differently to each other.)  There's one Perl slogan that'd
suggest having both ways in the language, so both of us get to code in
the way we like.

Countering that is the risk of adding too many ways of doing things and
just causing confusion for everybody with all the different ways of
invoking functions/methods on data.  Hence my quibble with who cares:
I could probably be persuaded that it's 'better' for the language not to
have the Perl 5 syntax, my preference, than to have so many alternative
syntaxes.  (I'm not sure.)

  Mike ... do you still find right-left pipelines as compelling as
  you've previously argued?
 
 Yes, very much so.  ... I've seen quite a few newbies struggle with
 the Cmap syntax;

Me too.  The most-strugglable bit for many has been the right-left data
flow, that you start by typing where you want the data to end up, then
the process it goes through last, then the process it goes through
first, and lastly the data that's being processed.  Left-right pipelines
should be great at fixing this.

 the most frequent mistake is to reverse the order of the arguments,
 saying
 
 map @a, {...}

That happens if you conceptualize Cmap as taking two arguments.  In my
mind Cmap operates on items in a list (and it just so happens that
in Perl an array provides a list):

  map { ... } $a, $b, $c;

So Cmap takes _many_ arguments, and one of these arguments is not like
the others.  And it makes sense to put the 'special' argument first.
(That's also how I remember which way round things like Cjoin are.)

Thinking of it as operating on a list of things also helps to emphasize
that Cmap processes just a single item at a time, that it isn't an
agregate operation on the items as a group.

 (Another common one is to not understand what 

Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-21 Thread Michael Lazzaro

On Tuesday, January 21, 2003, at 01:31  PM, Smylers wrote:

Michael Lazzaro wrote:

it's that I _dislike_ the perl5 rule, ...


Oh.  That's dislike rather than disliked?  My question was
predicated on your declaration I emphatically withdraw my objection,
which I took to mean that your knowledge of the infrared comma rule --
or whatever it's called -- meant you no longer disliked the Perl 5
syntax?


I still dislike it, but if a variation upon it means we can make things 
like Cfor, Cif, etc. semi-normal functions, instead of cases within 
the grammar, then I think everyone agrees that would be a Good Thing.  
Keeping one grammar special case in return for not having a dozen 
others -- yeah, I'll sign up for that.

I don't loath the old Cmap syntax to the point where I'd just die if 
it were there.  And I don't expect we'd really get rid of it, it's too 
intrinsic to Perl5.  At very minimum, we'd have to keep the global 
functions around as a module you could load for Perl5-friendliness.

I do think OO  pipelines are the better, more generic way to do the 
same thing.  So I'd really like to see pipelines, even if they're just 
in addition to the old Cmap style.  After that, it's just a question 
of whether the old style is worth the redundant declarations, which is 
purely a matter-of-taste thing.


the most frequent mistake is to reverse the order of the arguments,
saying
map @a, {...}

That happens if you conceptualize Cmap as taking two arguments.


I think you're right about that.  And we have both:

   for (@a) {...}
and
   map {...} @a;

Which stings some newbies repeatedly, poor lads.



Was that an understandable explanation?  :-)


Yes.  Thanks, again.  Please don't take personally my disagreeing with
so much you've written!


On the contrary.  I'm just so happy someone understood what I was 
trying to say, I think I'm going to burst into tears...  Wait, no... 
OK, I'm better now.

MikeL



Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-21 Thread Buddha Buck
Smylers wrote:

Michael Lazzaro wrote:





And it provides a very visual way to define any pipe-like algorithm, in 
either direction:

   $in - lex - parse - codify - optimize - $out;   # L2R

   $out - optimize - codify - parse - lex - $in;   # R2L

It's clear, from looking at either of those, that they represent data
pipes.


Yes; that is nice.  I'm just not convinced that it's sufficiently nice
to require adding yet another way of passing data around to the
language.  I'm happy enough with the asymmetry that occurs just having
the arrows to indicate 'reverse flow' data.


The problem with this example is that the two lines deal with two 
different calling conventions, going by Damian's proposal...

Perl 5 has two different code calling conventions:  object oriented 
method calls, and procedural subroutine calls.

OO method calls are L2R already:

  $object.method1().method2().method3().method4();

Procedural subroutine calls are R2L already:

  sub4 sub3 sub2 sub1 $variable;

But there is no way to do OO method calls R2L, and there is no way to do 
procedural subroutine calls L2R.

Damian's ~ and ~ proposal fills in this gap:

  method4 ~ method3 ~ method2 ~ method1 ~ $Xbject;
  $variable ~ sub1 ~ sub2 ~ sub3 ~ sub4;

To the best of my knowledge, the following two WILL NOT WORK:

  sub4 ~ sub3 ~ sub2 ~ sub1 ~ $variable;
  $Xbject ~ method1 ~ method2 ~ method3 ~ method4

The first one tries to invoke the sub1 method of $variable, while the 
second tries to call the method1 function with $object as an argument. 
If either of these works, it's either coincidence or careful planning.

So the apparant symmetry between ~ and ~ isn't really there.

I like ~ and ~, but I think that it will be a common mistake to think 
that $a ~ b~c~d can be reversed to give d~c~b~$a, when it can't. 
That, to me, is an argument against ~ and ~, at least as currently 
formulated.






Re: Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-21 Thread Michael Lazzaro

On Tuesday, January 21, 2003, at 02:38  PM, Buddha Buck wrote:

Michael Lazzaro wrote:

And it provides a very visual way to define any pipe-like algorithm, 
in either direction:
   $in - lex - parse - codify - optimize - $out;   # L2R

   $out - optimize - codify - parse - lex - $in;   # R2L

It's clear, from looking at either of those, that they represent data
pipes.
The problem with this example is that the two lines deal with two 
different calling conventions, going by Damian's proposal...
snip

So the apparant symmetry between ~ and ~ isn't really there.

I like ~ and ~, but I think that it will be a common mistake to 
think that $a ~ b~c~d can be reversed to give d~c~b~$a, when it 
can't. That, to me, is an argument against ~ and ~, at least as 
currently formulated.

Agreed, it could be quite misleading.  Personally, I'd be happier if ~ 
and ~ worked _only_ on objects and methods, instead of arbitrary 
subs... but I understand the utility of the other way.

Of course, _I'd_ even prefer using - and - as the 'piping' operators, 
and having ~ or | for pointy sub, because then $a-foo and $a.foo 
really _could_ be the same thing, 'cept for precedence.  But that's not 
gonna happen, and _I'm_ not gonna press it.  :-)

MikeL



Why Cmap needs work (was Re: L2R/R2L syntax)

2003-01-20 Thread Michael Lazzaro
On Monday, January 20, 2003, at 12:30  PM, Smylers wrote:

Ah.  It was only on reading that (and discovering that you hadn't
previously known about the 'optional comma with closure argument' rule)
that I understood why you had previously been so in favour of proposed
new syntaxes: through a desire to banish the Perl 5 syntax.


Yes.  Again, it's not that I never knew about the perl5 rule, it's that 
I _dislike_ the perl5 rule, as I dislike most special-case grammar 
rules.  If we dropped Cmap, etc., we could drop the inferred-comma 
rule as well (unless we're really successful in making Cif a simple 
function, in which case we need the rule anyway, so who cares?)

But the inferred-comma rule is tangential to my dislike of the current 
Cmap syntax.  I'd dislike Cmap, and like pipelines, even if the 
inferred-comma rule wasn't there.

Mike, now you've come to terms with the Perl 5 syntax, do you still 
find
right-left pipelines as compelling as you've previously argued?

Yes, very much so.  Here's why...

The Problem

Over the years, I've seen quite a few newbies struggle with the Cmap 
syntax; the most frequent mistake is to reverse the order of the 
arguments, saying

   map @a, {...}

(Another common one is to not understand what Cmap {...} @a, @b would 
do.)  There's a couple of reasons for that, IMO, but the wording I 
often get when I'm trying to get people to verbalize what this 
statement does is that it takes @a, and does blah to it.

In other words, when newcomers verbalize the statement, they tend to 
think of the Cmap as operating on @a.  Which is true.  You might also 
say it does blah to @a, which is also true.  For many people, the 
brain seems to lock around the C@a as the most important part of the 
statement, not the blah part.

Logically, that makes sense.  Cmap, Cgrep, etc., is an operation on 
@a.  It's not an operation on the {...} part -- the {...} is just an 
adverb describing the how, which is of lesser importance.

Is there an OO solution?

So is there fix for Cmap that wouldn't trip newbies up quite so much? 
 The simple fix would seem to be to emphasis the it operates on @a 
part, so that people more easily remember it from the way they 
verbalize it.  Obviously, an OO style fixes that easily:

   @a.map {...};

That's very intuitive to people, esp. new converts from other 
languages.  And, happily, it's very easy to implement and extend.  But 
it works only in one direction, L2R.  (And, as Damian stated, chaining:

   @a.map {...} .sort {...};

probably wouldn't work at all, unless you tossed some parens around all 
your curlies.  Yuck.)

So fine, we convert Cmap, etc., to be methods of collections, as is 
typical programming practice these days.  And, in fact, we _are_ doing 
that elsewhere in the language.  Things like Clength @a will become 
C@a.length or similar.  Even subscripts C[$n] can have dotted 
syntax, e.g. C.[$n].  And, presumably, there will be a C.map, 
C.grep, etc.

But in doing that, we lose a lot of functionality -- mainly, the simple 
L2R and R2L chaining that we have now.  So people want to keep Cmap 
as functions, not methods, and use the old syntax.  Well, that's OK, 
but we're back to the beginning.

 Is there a pipelike solution? 

People like the current Cmap syntax because it allows R2L chaining.  
Saying C @a.map {...}  isn't so onerous that it should send people 
reeling, since it's the exact same syntax as the entire rest of the 
language.  But losing the chaining would hurt, because it's a very 
useful feature.

Here's where the pipeline suggestions come in.  Looking at a strawman 
syntax using '-', JUST FOR THE SAKE OF IMPARTIAL EXAMPLE:

   @out = map {...} - @a;

That's two (OK, three) characters longer than the old syntax.  It could 
be described to newcomers as using @a, do blah with it.

Essentially, it's a post-invocant, a reversed way of saying C @a.map 
{...} .  Note that it doesn't rely on the existence of universal 
functions -- Cmap is just a method of @a.

Here's the important part:  This same syntax will work on ANY object, 
and ANY method of that object.  So you're removing the specific global 
functions Cmap, Cgrep, Csort, etc., and replacing them with a 
generic syntax for right-to-left chaining for any operations object.  
You don't have to _build_ functions that can support chaining, because 
_any_ method can be chained.

And it provides a very visual way to define any pipe-like algorithm, in 
either direction:

   $in - lex - parse - codify - optimize - $out;   # L2R

   $out - optimize - codify - parse - lex - $in;   # R2L

It's clear, from looking at either of those, that they represent data 
pipes.  Both are even clearer than the equiv:

   $out = $in.lex.parse.codify.optimize;

Whether you would code a pipeline as L2R or R2L depends on the specific 
algorithm you're representing, and is purely a matter of taste...  
you'd probably use R2L in the same places as you use Cmap-like 
chaining in Perl5.  I can't begin to justify