Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Pattern matching on arrays and "for" loops

6 views
Skip to first unread message

Luke Palmer

unread,
Jan 13, 2006, 4:15:25 PM1/13/06
to Dave Whipp, perl6-l...@perl.org
On 1/13/06, Dave Whipp <da...@whipp.name> wrote:
> I'm trying to work out if there's a clever perl6 way to write this using
> pattern matching:
>
> for @*ARGV -> "-f", $filename {
> $filename .= absolute_filename;
> }

There is, but it's a different kind of pattern matching:

if @*ARGV ~~ / <,> -f <,> (.*?) <,> / {
$0 .= absolute_filename;
}

Of course, that only works if you're allowed to modify the source
through the $# variables. I think you are, but I'm not certain.

This is a good example of how silly the current array matching
semantics are. You'd get a match for this call, because of
"carelessness" in writing the rule.

davesprog foo - f file

Because elements are implicitly concatenated together. The "correct"
way to write the rule is:

/ <,> - <!,> f <,> (.*?) <,> /

Isn't that dumb?

Here's what I counterpropose: matching against arrays treats each
element of the array as a single character. <()>-assertions make the
current character their topic. There is no <,>; it's implicit in the
character-element unification. Here's the new regex:

/ <( $_ eq '-f' )>. (.) /

This method makes more sense for a list of tokens, too.

We could shuffle around the special assertions to give shorthands for
these presumably common constructs:

<( ... )>.
<( $_ eq ... )>.
<( $_ ~~ /.../ )>.

The last one is the most important. It allows you to connect regexes
on a stream to regexes on an element of the stream. Possible
shorthands for those, respectively:

<+( ... )> # treating an assertion as a char class
<'...'> # hmm, already takes, maybe we could
# make a special case because it
# doesn't make much sense for
# nonstrings
</.../> # obvious

> Would this actually work, or would it stop at the first elem that
> doesn't match ("-f", ::Item)?

If by "stop" you mean "die", yes it would stop.

> Is there some way to associate alternate codeblocks for different
> patterns (i.e. local anonymous MMD)?

As Austin points out, that's called "given". I'll also point out that
if we have lookahead in "for" (a feature that I think is best reserved
for third-party modules):

for @*ARGV -> $cur, ?$next is rw {
if $cur eq '-f' {
$next .= absolute_filename;
}
}

Which isn't as slick as a pattern matching approach, but it gets the
job done without having to use indices.

Luke

Luke Palmer

unread,
Jan 13, 2006, 6:42:13 PM1/13/06
to Dave Whipp, perl6-l...@perl.org
On 1/13/06, Dave Whipp <da...@whipp.name> wrote:
> What happens if I simply abandon the attempt at anonymous MMD and use a
> named multi-sub, instead:
>
> {
> my multi sub process_arg("-f", Str $f is rw) {
> $f .= absolute_filename
> }
> my multi sub process_arg("--quux", Str arg1, Str arg2) { ... }
> ...
> my multi sub process_arg(Str _) {} # skip unrecognised args
>
> for @*ARGV: &process_arg;
> }

Oh, that's a clever way to process arguments. A module could probably
turn that into a nice declarative option parsing library.

Unfortuately, it the form you've written above, that doesn't work.
That's because process_arg does not have a well-defined arity, so
"for" doesn't know how many elements to pull of the list each time.
In order to do that correctly, there would have to be some very fine
communication between for and the signature pattern matcher.

I could definitely see a library doing this though:

getopts @*ARGV,
-> '-f', Str $f is rw {...},
-> '--quux', Str $arg1, Str $arg2 {...},
-> $ { }; # ignore

It is likely doable without any magic too wicked, too.

Luke

Dave Whipp

unread,
Jan 13, 2006, 6:18:08 PM1/13/06
to perl6-l...@perl.org
Luke Palmer wrote:
> On 1/13/06, Dave Whipp <da...@whipp.name> wrote:

>>Would this actually work, or would it stop at the first elem that
>>doesn't match ("-f", ::Item)?
>
> If by "stop" you mean "die", yes it would stop.

not what I wanted :-(

>>Is there some way to associate alternate codeblocks for different
>>patterns (i.e. local anonymous MMD)?
>
> As Austin points out, that's called "given". I'll also point out that
> if we have lookahead in "for" (a feature that I think is best reserved
> for third-party modules):
>
> for @*ARGV -> $cur, ?$next is rw {
> if $cur eq '-f' {
> $next .= absolute_filename;
> }
> }
>
> Which isn't as slick as a pattern matching approach, but it gets the
> job done without having to use indices.

What happens if I simply abandon the attempt at anonymous MMD and use a

Larry Wall

unread,
Jan 13, 2006, 6:59:09 PM1/13/06
to perl6-l...@perl.org

That doesn't seem sufficiently general. I'd rather see some context
that can apply a signature to the head of a list and treat the
"unslurped" part as unmatched. Maybe a "for" loop could be taught
to supply such a context, or a "when". Or maybe it's just the result
of embedding a sig inside a rule, or of matching a sig using ~~.

Basically, we just have to find a way to treat the sig as a pattern
that isn't anchored at the end.

Larry

Brad Bowman

unread,
Jan 14, 2006, 8:51:26 AM1/14/06
to la...@wall.org, perl6-l...@perl.org
On 14/01/06 00:59, Larry Wall wrote:
> That doesn't seem sufficiently general. I'd rather see some context
> that can apply a signature to the head of a list and treat the
> "unslurped" part as unmatched. Maybe a "for" loop could be taught
> to supply such a context, or a "when". Or maybe it's just the result
> of embedding a sig inside a rule, or of matching a sig using ~~.

Could the sharp end of a pipe be taught to do this?

I suggested something like this before but Luke pointed out that it
was adding unnecessary DWIMiness. Perhaps this use case could revive
the idea:

http://groups.google.com/group/perl.perl6.language/browse_thread/thread/3d403aa8ff6e493e/ac666ce340cf819b

Brad

--
There are two things that will blemish a retainer, these are riches and
honor. But if one remains in strained circumstances he will not be
marred. -- Hagakure http://bereft.net/hagakure/

0 new messages