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

Run time dispatch on ~~

1 view
Skip to first unread message

Aaron Sherman

unread,
Jul 13, 2006, 3:44:33 PM7/13/06
to Perl6 Language List
I'm told that I did a terrible job of making my point in the === thread,
and nothingmuch asked me on IRC to re-state my concerns. I'll do so
briefly, and then give examples. Please do have a look at the examples,
just in case I'm not clear.

Overview:

~~ is great. It matches on all kinds of useful right-hand-sides like
regexes, strings, methods, your neighbor's kids, you-name-it.

The only problem that I have is ~~ matching against an unknown type
(Any~~Any). In this case, the programmer cannot know what it is that
they're getting themselves into, and for the life of me, I can't see why
Perl would do anything other than an only slightly smart comparison
there, since that's obviously what the programmer had in mind.

However, S03 specs that ~~ will do a run-time dispatch based on the type
of that value at the time. Matching Arrays (@~~@) is just a
hyperoperated case of the same problem, except for the case where the
array on the right-hand-side can be typed at compile-time or is a list
that can be coerced painlessly into such a typed array. Then there's no
dispatch at run-time.

Solution:

Ok, so first let me re-propose my solution: Any~~Any and @~~@ are
compile-time dispatched to =~= and >>=~=<< respectively (no, I'm not
married to the name, and perhaps eqv is better for this, I don't know),
which has some smarts about comparing values in meaningful ways, and
which programmers know to override if they really need special matching
semantics, but basically is just a very slightly smarter ===. Regexes
are compared, not executed. Code is compared, not executed.

Examples:

Now, let's look at some of the good that ~~ does for us:

$a ~~ "Some string" # sameness
$a ~~ 5 # sameness
$a ~~ ->{...} # test
$a ~~ /.../ # regex matching

That's great, and we don't want to mess with any of it.

But, then we have:

$a ~~ $b # uh... something

We can't even say what it does, much less why it's useful. It does
"match" whatever that is. Sure, it's great for implementing your own ~~,
but that's about it.

The even worse:

@a ~~ @b # uh... lots of something

looks like array comparison to the casually misinformed user, but is
actually a run-time, hyperized vector dispatch...

Now, I do think people will want to:

@a ~~ ( /^\d+$/, /^\w+$/, /^\s+$/ )

but we can coerce that into a typed array at compile time, so there's no
problem.

Going with my suggestion would mean that ~~ is still very powerful, just
not opaque. You would have to ask for it to activate a particular
superpower by giving it a right-hand-side that has a type, or expect a
fairly mundane comparison to be performed.

The _security_ implications will likely get sorted out, but I still
forsee some major end-user bogglage when $a~~$b is true, even though
they have no relationship to each other that was obvious to the
programmer who wrote the statement.

Keep in mind that if you have an Any and you want to match against it
smartly, you can always request your poison:

$a ~~ ($b as Regex)

--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"We had some good machines, but they don't work no more." -Shriekback


Yuval Kogman

unread,
Jul 13, 2006, 5:08:23 PM7/13/06
to Aaron Sherman, Perl6 Language List
On Thu, Jul 13, 2006 at 15:44:33 -0400, Aaron Sherman wrote:

> Now, let's look at some of the good that ~~ does for us:
>
> $a ~~ "Some string" # sameness
> $a ~~ 5 # sameness
> $a ~~ ->{...} # test
> $a ~~ /.../ # regex matching
>
> That's great, and we don't want to mess with any of it.
>
> But, then we have:
>
> $a ~~ $b # uh... something


One compelling reason to have them behave exactly the same is to
allow refactoring.

If i'm using the same pattern on several inputs i'd like to maybe
delegate this to a helper sub that will actually run the ~~ for me,
in some way, and i'd like 100% compatibility.

Also, sometimes i am matching on behalf of my caller, this is very
common in dispatch algorithms, or things like tree visitors:

my @list = $tree.filter_children( $match ); # very generic and useful


--
Yuval Kogman <nothi...@woobling.org>
http://nothingmuch.woobling.org 0xEBD27418

Aaron Sherman

unread,
Jul 14, 2006, 10:05:32 AM7/14/06
to Yuval Kogman, Perl6 Language List
On Fri, 2006-07-14 at 00:08 +0300, Yuval Kogman wrote:

> Also, sometimes i am matching on behalf of my caller, this is very
> common in dispatch algorithms, or things like tree visitors:
>
> my @list = $tree.filter_children( $match ); # very generic and useful

It's really the fact that that's a method that hoses everything. There's
essentially no way to compile-time dispatch that, so even macros won't
help you.... grr.

No, you've got me. There needs to be a way to do that, but oh dear it's
going to be confusing, and as ever, I worry about those who will use
this sort of thing poorly or mistakenly, and then rant on about how Perl
is write-only.

Perhaps the solution is not code, but documentation. Perhaps if we make
a clean break between comparison and matching in the docs, and push
people away from non-regex/string-~~ until they understand its
implications, we can head off much of the lossage.

For example (modified S03 "Smart matching" section without the table):

=head1 Smart matching

Smart matching is the process of asking, does thing I<a> conform to the
specification of I<b>? The most common reason to want to do this is to
match a string against a regex:

if $s ~~ /^\d+$/ { ... }

But smart matching is also performed by given/when for switch-like behavior:

given $s {
when 'Apple' { ... }
when 'Pear' { ... }
default { die "No fruit!" }
}

Notice that the specification can also be a string, as above, but because
C<eqv> and C<~~> mean the same thing in this context, it is clearer, when
writing a single expression to explicitly use C<eqv>:

if $a eqv $b { ... }

The right-hand side of C<~~> (the specification) always controls the
nature of the matching, so care must be taken when matching. Do not
think of this as simple "comparison" where the arguments are considered
peers.

Here is the current table of smart matches with respect to $_ and $x
as they would be used here:

given $_ {
when $x {...}
}

or

$_ ~~ $x

The list is intended to reflect forms that can be recognized at
compile time. If none of these forms is recognized at compile time, it
falls through to do MMD to C<< infix:<~~>() >>, which presumably
reflects similar semantics, but can finesse things that aren't exact
type matches. Note that all types are scalarized here. Both C<~~>
and C<given>/C<when> provide scalar contexts to their arguments.
(You can always hyperize C<~~> explicitly, though.)

Both C<$_> (the value) and C<$x> (the match specification) here are
potentially references to container objects.
And since lists promote to arrays in scalar context, there need be no
separate entries for lists.

(table goes here)

Dr.Ruud

unread,
Jul 14, 2006, 10:34:26 AM7/14/06
to perl6-l...@perl.org
Aaron Sherman schreef:

> given $_ {
> when $x {...}
> }
>
> or
>
> $_ ~~ $x

Can that be written as ".~~ $x"?

--
Affijn, Ruud

"Gewoon is een tijger."


Larry Wall

unread,
Jul 14, 2006, 3:09:45 PM7/14/06
to perl6-l...@perl.org
On Fri, Jul 14, 2006 at 04:34:26PM +0200, Dr.Ruud wrote:
: Aaron Sherman schreef:

:
: > given $_ {
: > when $x {...}
: > }
: >
: > or
: >
: > $_ ~~ $x
:
: Can that be written as ".~~ $x"?

No, but you might just possibly get away with writing:

.infix:<~~>($x)

assuming that the $_.foo($x) SMD eventually fails over to foo($_,$x) MMD.
But that doesn't seem to be much of an improvement over "when $x".

Larry

Dr.Ruud

unread,
Jul 14, 2006, 4:15:41 PM7/14/06
to perl6-l...@perl.org
Larry Wall schreef:
> Dr.Ruud:
>> Aaron Sherman:

>>> $_ ~~ $x
>>
>> Can that be written as ".~~ $x"?
>
> No, but you might just possibly get away with writing:
>
> .infix:<~~>($x)
>
> assuming that the $_.foo($x) SMD eventually fails over to foo($_,$x)
> MMD. But that doesn't seem to be much of an improvement over "when
> $x".

OK, thanks. Is it ever useful for an SMD to fail over to MMD?

0 new messages