develooper Front page | perl.perl6.language | Postings from August 2002

Re: RFC261 in Perl 5 and where it needs Perl 6 support

Thread Previous
From:
Steve Fink
Date:
August 6, 2002 19:26
Subject:
Re: RFC261 in Perl 5 and where it needs Perl 6 support
Message ID:
20020807022555.GK2114@foxglove.digital-integrity.com
On Thu, Jun 06, 2002 at 06:06:16PM -0400, Aaron Sherman wrote:
> 
> Larry discounted RFC261 in A5, but I think there's some good in it. The
> biggest problem is not that it's hard to do in Perl6, but that 80-90% of
> it is ALREADY done in Perl5! Once you peel away that portion of the RFC,
> you get to Perl5's limitations and what Perl6 might do to support these
> things.

It's certainly easy to do many of the same things in perl5. In fact,
way before I wrote that RFC, I wrote a simple perl5 module that
implemented most of the RFC (except it took the left hand side of the
match as a string, and could only assign to pre-existing variables).
But the point is to do it all declaratively.

> NOTE: My examples are unchecked, so they should be considered
> pseudo-code.

So were the ones in the RFC -- I kind of slapped it together at the
last minute before the RFC process closed. (And it shows.)

> #RFC261
>     match { 'Joe' => ? } = $h or die "Hash does not contain Joe";
> #Perl5
>     scalar(grep { $_ eq 'Joe' } keys %$h) or die ...

Yours is more verbose and slower. I'd probably rewrite that as

  exists $h->{Joe} or die...

although it should probably act more like

  defined($h) && UNIVERSAL::isa($h, 'HASH') && exists $h->{Joe} or die...

> # This one states its own solution
>     # Equiv to scalar(grep { $_ == 1 } @list)
>       match (..., 1, ...) = @list;
> 
> # No idea what this is supposed to do. I think $_[$_] is meant to work
> # in a way it doesn't ($_ will be a value, not an index).
>     # Pretty close to ($idx) = grep { $_[$_] == 1 } @_; $b = $_[$idx+1];
>       match (..., 1, $b) = @_;

oops. Yes, that should have said 0..$#_ where it said @_. It sets $b
to the element after the first 1 in the list, if there is a 1 in the
list. But you've got to agree that the match() form is a lot easier to
understand...

> # However, I want to suggest that Perl6 closures on grep and map should
> # be considered anonymous methods on the implied loop itself, so that we
> # can call methods like .index or .prev or .next (look ahead/behind), etc.
> # This gets sticky in some situations, but it would be invaluable, so it's
> # worth the effort, IMHO.

Isn't there already some perl6 way to access the index? I agree with
its usefulness. Not so sure about .prev and .next (the latter scares
me).

> # RFC
>     # It gets worse! This gives the value associated with a key matching the
>       # regular expression a*b:
>       match { /a*b/ => $value } = \%h;
> #Perl5
>     # The RFC does not account for multiple matches
>     # (presumably we just take the first)
>     ($value) = map {$h{$_}} grep {/a*b/} keys %h;

Good enough. I'm sure you could get clever and stick in a
{ ... && last } somewhere to get the first one and abort the
processing.

My intent with the RFC would probably be for it to be legal to return
anything that matches the pattern, choosing between them arbitrarily.
That makes the most sense to me when thinking of it declaratively. (If
it were another expression that it mapped to instead of just $value,
however, then it would need to pick the one that matched the
expression.)

> # RFC
>     # And if you want to know what the key was:
>       match { $key = /a*b/ => $value } = \%h;
> # Perl5
>     ($key,$value) = map {($_,$h{$_})} grep {/a*b/} keys %h;
>     
> # RFC
>     # What if you want to grab out the index? This is like
>       # ($i) = grep { $list[$_] =~ /foo/ } 0..$#list
>       match ( $i => /foo/ ) = @list;
> # Perl5
>     # As suggested above
> # Perl6
>     # See my previous comment on closures of this type
>     grep {/foo/ && $i = .index} @list;
> 
> Sorry, it's time for me to go meet someone, but I think the rest of the
> RFC just gets into two cases. One involves some funky OO stuff that I'm
> not going to touch on here. The other is the idea of matching sub-lists,
> which would be the place for some methods inside of grep and map that
> support look ahead and behind.
> 
> I hope others will take up this line of thought. Improved list
> manipulation can only be a good thing, IMHO.

You're saying that it's simple enough to do most of this that we
should look at adding the minimum necessary to make the rest of it
easy too.

I would rather have a declarative syntax for doing these sorts of
things. Though it boils down to the same thing -- I'd actually rather
not have the core language burdened by this stuff, but I *would* like
to be able to write a module that implements all of it. That
implementation would be much easier with exactly the sorts of support
you suggest. It requires more than that, however, to get the
declarative syntax, but it sounds like the parser should be hackable
enough to do the declarative syntax part too.

I have two arguments for the declarative syntax: first, I think it's
easier to read than a hairball of nested maps and greps. Second, I
think that the amount of work required to change the declarative
syntax is much closer to the magnitude of the change. Consider:

  RFC: match { body => $body } = $html_tree;
  perl5: $body = $html_tree->{body};

Oops, $html_tree doesn't have normalized case, so we have to allow
Body and BODY too:

  RFC: match { /body/i => $body } = $html_tree;
  perl5: ($body) = grep { /body/i && $html_tree->{$_} } keys %$html_tree;

Oh, wait, we need to pull out the head section also:

  RFC: match { /body/i => $body, /head/i => $head } = $html_tree;
  perl5: ($body) = grep { /body/i && $html_tree->{$_} } keys %$html_tree;
         ($head) = grep { /head/i && $html_tree->{$_} } keys %$html_tree;

(slow!) or

  perl5: while (($k,$v) = each %$html_tree) { $body = $v if $k =~ /body/i;
                                              $head = $v if $k =~ /head/i; }

Small changes in what you want to do lead to dramatic changes in the
perl5 code. Unless, of course, you start out with the most general
form of the perl5 code, in which case the modifications are much more
straightforward -- but then when you want to do something trivial, you
have to write something horribly slow and complicated.

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About