Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters

fixing smartmatch just hard enough (and when, too)

 

 

First page Previous page 1 2 3 4 5 6 Next page Last page  View All Perl porters RSS feed   Index | Next | Previous | View Threaded


perl.p5p at rjbs

Aug 16, 2012, 2:58 PM

Post #1 of 140 (208 views)
Permalink
fixing smartmatch just hard enough (and when, too)

So, last year I said "we really ought to cut most of smart match away."

http://www.nntp.perl.org/group/perl.perl5.porters/2011/07/msg174272.html

I've slept on it about 380 times, and I'm still for it. Here's the new plan:

## The New ~~ Operator

$a $b Meaning
======= ======= ======================
Any undef ! defined $a
Any ~~-overloaded ~~ overloading is used
~~-ol Any ~~ overloading is used (reversed)
Any CodeRef, &{}-ol $b->($a)
Any Regexp, qr-ol $a =~ $b
Any Simple $a eq $b
Any Any fatal

This is a nearly a subset of the current behavior. Here are some major points:

(1) This is ordered for the sake of knowing which overload to use first.

(2) A simple scalar (non-reference, non-glob, non-vstring) on the rhs is
used for stringwise equality. I have not yet seen any convincing argument
that we can correctly intuit an eq/== behavior, so we pick one.

Forcing numeric comparison can be done with things like the helpers found in
Smart::Match: things to produce a CodeRef that has the correct behavior.

(3) Container types (array, hash) are no longer treated specially. They were
the most unintuitive case, and they get kicked out. More on that later.

This gets is back to what I've always said is the real power of ~~: a
simple way to provide "a test" to run against a value, where the creator of the
value know just how it will be used. With one exception, we're dispatching
entirely based on the rhs, and they're all obvious.

"Oh no!" you may cry, "What about $x~~@opts? All I wanted was an `in`
operator!"

## Core Junctions

Well, that's why we have junctions. Remember those? Of course you do, they're
fantastic.

if ($x ~~ any( qw( John Paul Ringo ) )) {
tune_strings;
} else {
tap_drumps;
}

We already have very nice junctions in Perl6::Junction. We bring that into the
core (with a new name) and we get nice useful ways to put tests together. We
also get them anywhere else we want them. For me, that's "all over the place."
I bet it will be for lots of other people, too.

## Backcompat and ~~

My anxiety over backward compatibility for ~~ is not gut-wrenching. Still, it
would be nice to do what we can.

After a lot of talk about making ~~ pluggable across different scopes, I think
it's a non-starter. It's just not the kind of thing we can plug this way,
because of the way in which we expect it to be used. If we expect users to
pass a test from their code to some other code, they need to know how that code
will use it. It needs to be the same everywhere.

It would be nice to provide a best-effort backcompat with a deprecation warning
when possible. I'd like to know how good that effort can be. Since the new
table is in many ways a subset of the old one, I think it can be pretty good.

As previously mentioned, the "switch" feature is considered highly
experimental; it is subject to change with little notice. In
particular, both "given" and "when" have tricky behaviours that are
expected to change to become less tricky in the future. Do not rely
upon their current (mis)implementations.
-- perlsyn

## Fixing given and when

I think we already fixed given pretty hard. I need to look at bit more at it,
but let's take it as "fixed enough" for now.

when!

Oh, when, how you trouble me.

I propose that `when(X)` *always* means `$_ ~~ X`. All of the special cases
for parsing and interpreting the inside of when can go. They can all be
reduced to `when(sub{...})`. I would also smile upon `when({...})` acting as a
test block. (Since you can't put a hashref on the rhs of ~~ anymore, there is
no ambiguity.)

The exceptions (from perlsyn's "Experimental Details on given and when") are:

EXCEPTION WAS IS NOW
1. subroutine call -- when (foo())) -- when ({ foo() })
2. regex match -- when ( /foo/ ) -- when (qr/foo/)
-- when ( $_ !~ /foo/) -- when ( none( qr/foo/ ) )
3. smart match -- when ($a ~~ $b) -- when ({ $a ~~ $b })
4. comparison -- when ($a lt $b) -- when ({ $a lt $b })
5. some builtins -- when (eof) -- when ({ eof })
6. negation -- when (! $x) -- when ({ ! $x })
7. bool filetest -- when (-r) -- when ({ -r })
8. flip flops -- when ($a .. $b) -- when ({ $a .. $b })
9. conjunction -- when ($a && $b) -- when ( all( $a, $b ) )
or when ({ $a && $b })
0. disjunction -- when ($a || $b) -- when ( any( $a, $b ) )
or when ({ $a || $b })

Also, `when` should be valid inside an auto-topicalizing `while`, providing an
implicit next, making its behavior more generic so that `when` can be used
safely everywhere that it makes sense.

## In Conclusion

I think this makes ~~ and given/when both totally predictable. I've gone over
this design quite a bit, and I think it turns these features from a liability
to an asset. I also think that we'll be able to eliminate quite a lot of
documentation, which I take as a very good sign. (A lot of that documentation
includes things like "this part is really hard to understand.")

When ~~ works like this, I will use it all the time.

--
rjbs
Attachments: signature.asc (0.48 KB)


xdaveg at gmail

Aug 16, 2012, 3:19 PM

Post #2 of 140 (195 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Thu, Aug 16, 2012 at 5:58 PM, Ricardo Signes
<perl.p5p [at] rjbs> wrote:
> ## The New ~~ Operator

+1

> ## Core Junctions

+1 (maybe more)

> ## Backcompat and ~~

/me shrugs. Maybe just rip the band-aid off and get it over with.

> ## Fixing given and when

+0.5 → because when({...}) is darn ugly nesting. Since a naked "when"
(without a test) is illegal, could we get this syntax working?

when (...) {...} # smart-match
when {...} {...} # code-ref
when {...} # syntax error

-- david


rs at 474

Aug 16, 2012, 3:43 PM

Post #3 of 140 (193 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Thu, 2012-08-16 at 17:58 -0400, Ricardo Signes wrote:
> So, last year I said "we really ought to cut most of smart match away."
>
> http://www.nntp.perl.org/group/perl.perl5.porters/2011/07/msg174272.html
>
> I've slept on it about 380 times, and I'm still for it. Here's the new plan:

That would be very nice.

> (2) A simple scalar (non-reference, non-glob, non-vstring) on the rhs is
> used for stringwise equality. I have not yet seen any convincing argument
> that we can correctly intuit an eq/== behavior, so we pick one.

Seems sensible. I'd also add an advantage of picking the string equality
test: Very often when I want to compare numbers, I don't just want to
compare equality. I want to compare ranges, if they are larger or
smaller, and so on. I don't do this with strings very often. I do use
string non-equality sometimes, but less often, and that would be solved
by `({...})` below without much overhead.

But of course that's just my use-case.

> I propose that `when(X)` *always* means `$_ ~~ X`. All of the special cases
> for parsing and interpreting the inside of when can go. They can all be
> reduced to `when(sub{...})`. I would also smile upon `when({...})` acting as a
> test block. (Since you can't put a hashref on the rhs of ~~ anymore, there is
> no ambiguity.)

That would make it certainly easier. With regard to `when ({...})`,
would that be a block as in `do {...}`? That would be nicely explicit
and efficient. I might for example not want to `when(sub { ... })` in a
high frequency loop. Being able to just have a block there would speed
that up.

The `when {...} {...}` variant proposed by David Golden would have the
advantage of being "explicitly special" and people might be more
discouraged trying to combine the `{...}` with, for example, junctions.

It'd also mean people having hash references there now can't be
surprised somehow.

> When ~~ works like this, I will use it all the time.

When I use ~~ now, I already use it mostly like you propose (except for
the new syntax bits).

regards,
--
Robert 'phaylon' Sedlacek

Perl 5 Consultant for
Shadowcat Systems Limited - http://shadowcat.co.uk/


fawaka at gmail

Aug 17, 2012, 3:13 AM

Post #4 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 12:58 AM, Ricardo Signes
<perl.p5p [at] rjbs> wrote:
> ## The New ~~ Operator
>
> $a $b Meaning
> ======= ======= ======================
> Any undef ! defined $a
> Any ~~-overloaded ~~ overloading is used
> ~~-ol Any ~~ overloading is used (reversed)
> Any CodeRef, &{}-ol $b->($a)
> Any Regexp, qr-ol $a =~ $b
> Any Simple $a eq $b
> Any Any fatal
>
> This is a nearly a subset of the current behavior. Here are some major points:

I'm not quite sure about the reversed overloading, but otherwise
that'd be my list too.

> ## Core Junctions
>
> Well, that's why we have junctions. Remember those? Of course you do, they're
> fantastic.
>
> if ($x ~~ any( qw( John Paul Ringo ) )) {
> tune_strings;
> } else {
> tap_drumps;
> }
>
> We already have very nice junctions in Perl6::Junction. We bring that into the
> core (with a new name) and we get nice useful ways to put tests together. We
> also get them anywhere else we want them. For me, that's "all over the place."
> I bet it will be for lots of other people, too.

Yeah, we should totally have that in core.

> ## Backcompat and ~~
>
> My anxiety over backward compatibility for ~~ is not gut-wrenching. Still, it
> would be nice to do what we can.
>
> After a lot of talk about making ~~ pluggable across different scopes, I think
> it's a non-starter. It's just not the kind of thing we can plug this way,
> because of the way in which we expect it to be used. If we expect users to
> pass a test from their code to some other code, they need to know how that code
> will use it. It needs to be the same everywhere.
>
> It would be nice to provide a best-effort backcompat with a deprecation warning
> when possible. I'd like to know how good that effort can be. Since the new
> table is in many ways a subset of the old one, I think it can be pretty good.

I think a CPAN-smoke for this could be most helpful. We don't really
know how much code would break, even if it probably isn't all that
much.

> ## Fixing given and when
>
> I think we already fixed given pretty hard. I need to look at bit more at it,
> but let's take it as "fixed enough" for now.
>
> when!
>
> Oh, when, how you trouble me.
>
> I propose that `when(X)` *always* means `$_ ~~ X`. All of the special cases
> for parsing and interpreting the inside of when can go. They can all be
> reduced to `when(sub{...})`. I would also smile upon `when({...})` acting as a
> test block. (Since you can't put a hashref on the rhs of ~~ anymore, there is
> no ambiguity.)
>
> The exceptions (from perlsyn's "Experimental Details on given and when") are:
>
> EXCEPTION WAS IS NOW
> 1. subroutine call -- when (foo())) -- when ({ foo() })
> 2. regex match -- when ( /foo/ ) -- when (qr/foo/)
> -- when ( $_ !~ /foo/) -- when ( none( qr/foo/ ) )
> 3. smart match -- when ($a ~~ $b) -- when ({ $a ~~ $b })
> 4. comparison -- when ($a lt $b) -- when ({ $a lt $b })
> 5. some builtins -- when (eof) -- when ({ eof })
> 6. negation -- when (! $x) -- when ({ ! $x })
> 7. bool filetest -- when (-r) -- when ({ -r })
> 8. flip flops -- when ($a .. $b) -- when ({ $a .. $b })
> 9. conjunction -- when ($a && $b) -- when ( all( $a, $b ) )
> or when ({ $a && $b })
> 0. disjunction -- when ($a || $b) -- when ( any( $a, $b ) )
> or when ({ $a || $b })

I agree this is an issue, but I'm really not sure I like this
solution, not that I have a better idea.

> Also, `when` should be valid inside an auto-topicalizing `while`, providing an
> implicit next, making its behavior more generic so that `when` can be used
> safely everywhere that it makes sense.

Yes please.

Leon


eda at waniasset

Aug 17, 2012, 3:39 AM

Post #5 of 140 (187 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

Hmm, I understand the enthusiasm for magic junction types like 'any', since
Perl 6 has them, and Perl 6 is somehow related to Perl 5 in some way, but I
still feel that a simple 'in' operator would be far more straightforward.

if ($x in @a)

Reading that you immediately see what it is going to do: the Perl interpreter
will loop over each element in @a, do an equality comparison against $x (and
I do entirely agree that string equality is the way to go) and stop when one
is found.

The semantics of 'any' are much less straightforward, especially if you want
to reason about memory usage. Does creating the junction object involve taking
a copy of the array? More importantly, the 'any' junction cannot be used to
implement a list membership test that works in all cases.

my $j1 = any(qw(a b));
my $j2 = any(qw(c d));
my $j = any($j1, $j2);
if ('a' eq any($j)) { say 'yes a' }
if ($j1 eq any($j)) { say 'yes j1' }

Clearly, it cannot be the case that both 'a' and $j1 are members of the list
($j1, $j2). Junctions surely have all sorts of interesting uses, but they are
not a substitute for a simple list membership operator.

Let's use the simplest possible syntax, with the simplest possible semantics.

--
Ed Avis <eda [at] waniasset>


perl.p5p at rjbs

Aug 17, 2012, 4:42 AM

Post #6 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

* Leon Timmermans <fawaka [at] gmail> [2012-08-17T06:13:12]
> I'm not quite sure about the reversed overloading, but otherwise
> that'd be my list too.

I wasn't super keen on it, but I remembered that autodie's exceptions use it
like this, and that use case seems quite reasonable. I think omitting it would
be a mistake.

--
rjbs
Attachments: signature.asc (0.48 KB)


Eirik-Berg.Hanssen at allverden

Aug 17, 2012, 5:06 AM

Post #7 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 12:39 PM, Ed Avis <eda [at] waniasset> wrote:

> Hmm, I understand the enthusiasm for magic junction types like 'any', since
> Perl 6 has them, and Perl 6 is somehow related to Perl 5 in some way, but I
> still feel that a simple 'in' operator would be far more straightforward.
>
> if ($x in @a)
>
> Reading that you immediately see what it is going to do: the Perl
> interpreter
> will loop over each element in @a, do an equality comparison against $x
> (and
> I do entirely agree that string equality is the way to go) and stop when
> one
> is found.
>

1)
Ah, but if you have junctions, you are not restricted to one type of
equality, or even to equality tests.

if ($x eq any(@a)

if ($x < any(@a))

if ($x =~ any(@a)) # assuming more Perl 6-like semantics, not the
Perl6::Junction implementation

if (any(@a) =~ $x) # likewise

if (any(@a)->accepts($x)) # likewise

if ($x->accepts(any(@a))) # um ...

... and that's not even counting the other kinds of junctions ...


2)
But, as noted in my comments above, the Perl6::Junction implementation
does not do all that Perl 6 leads me to expect.

I mean, hey, they currently don't even allow C<< any(2,3,4) * 2 == 8 >>,
do they? See
http://search.cpan.org/~cfranks/Perl6-Junction-1.40000/lib/Perl6/Junction.pm#TO_DO

I don't think Perl6::Junction is ready for core. I don't know how much
it would take to make junctions ready for core.

I'm not even sure what semantics they should have. As you say:



> The semantics of 'any' are much less straightforward, especially if you
> want
> to reason about memory usage. Does creating the junction object involve
> taking
> a copy of the array? More importantly, the 'any' junction cannot be used
> to
> implement a list membership test that works in all cases.
>
> my $j1 = any(qw(a b));
> my $j2 = any(qw(c d));
> my $j = any($j1, $j2);
> if ('a' eq any($j)) { say 'yes a' }
> if ($j1 eq any($j)) { say 'yes j1' }
>
> Clearly, it cannot be the case that both 'a' and $j1 are members of the
> list
> ($j1, $j2).


3)
Clearly you don't mean to be testing with C<eq> here. Both 'a' and $j1
are C<eq> to some member of the list C<< $j1, $j2 >>. Since that's not
what you want, you'll have to write a test that DWYW.

Conceptually – what is "list membership"? C<< first { eqv($item, $_) }
@list >>, perhaps? If so, how would you define that C<< eqv >>?
(Conceptually. Worry about implementation later.)

(Too terse? Let me try to expand it: If your C<eqv> is merely C<eq>,
you'll have to accept that stuff that overloads C<eq>, like junctions, have
their own idea of list membership. If one item in your list is the $j1
junction above, this definition will grant both 'a' and $j1 membership in
your list.)


Eirik


eda at waniasset

Aug 17, 2012, 5:20 AM

Post #8 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

Eirik Berg Hanssen <Eirik-Berg.Hanssen <at> allverden.no> writes:

>If your C<eqv> is merely C<eq>, you'll have to accept that stuff that overloads
>C<eq>, like junctions, have their own idea of list membership.

Good point. I was assuming that there is a concept of scalar equality defined
by the language and accessible to the programmer directly. But this is not the
case, it seems; you cannot use 'eq' to reliably compare two scalars for equality,
since C<'a' eq any('a')> even though 'a' and
'Perl6::Junction::Any=ARRAY(0x2488048)' are manifestly different things.

If there is not a reliable equality operator then it makes no sense to ask for
a list membership operator. So perhaps C<$x eq any(@a)> is the best we are going
to get, even though as mentioned it does not reliably test list membership.

--
Ed Avis <eda [at] waniasset>


xdaveg at gmail

Aug 17, 2012, 5:50 AM

Post #9 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 8:20 AM, Ed Avis <eda [at] waniasset> wrote:
>
> Good point. I was assuming that there is a concept of scalar equality defined
> by the language and accessible to the programmer directly. But this is not the

Perl gives you numeric and string equality (and allows overriding of
each). Consider this:

use v5.10;
use strict;
use warnings;
use bignum;
use Scalar::Util qw/refaddr/;

my $x = 42;
my $y = 42;

say '$x is object at ' . refaddr($x);
say '$y is object at ' . refaddr($y);

# output:
# $x is object at 40813776
# $y is object at 40814952

If you tested C<< $x in ( $y ) >>, is that true or false? $x and $y
are different objects, yet the compare true numerically. Is $x in the
list or not?

Thus your conception of "in" is visually elegant -- and I like that --
but just isn't specific enough for the dynamic nature of Perl, whereas
junctions force the programmer to clarify what comparison they
actually want for a membership test.

C<< $x == any( $y ) >>
C<< refaddr($x) == any( map { refaddr $_ } $y ) >>

-- David


abigail at abigail

Aug 17, 2012, 6:24 AM

Post #10 of 140 (186 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Thu, Aug 16, 2012 at 05:58:16PM -0400, Ricardo Signes wrote:
>
> So, last year I said "we really ought to cut most of smart match away."
>
> http://www.nntp.perl.org/group/perl.perl5.porters/2011/07/msg174272.html
>
> I've slept on it about 380 times, and I'm still for it. Here's the new plan:
>
> ## The New ~~ Operator
>
> $a $b Meaning
> ======= ======= ======================
> Any undef ! defined $a
> Any ~~-overloaded ~~ overloading is used
> ~~-ol Any ~~ overloading is used (reversed)
> Any CodeRef, &{}-ol $b->($a)
> Any Regexp, qr-ol $a =~ $b
> Any Simple $a eq $b
> Any Any fatal
>
> This is a nearly a subset of the current behavior. Here are some major points:
>
> (1) This is ordered for the sake of knowing which overload to use first.
>
> (2) A simple scalar (non-reference, non-glob, non-vstring) on the rhs is
> used for stringwise equality. I have not yet seen any convincing argument
> that we can correctly intuit an eq/== behavior, so we pick one.

For me, one of the few advantages I saw in using ~~ is not having to
wonder when to use == vs eq vs =~. The above table suggests that

"0.0" ~~ 0

is false, while it's currently true. That bothers me. IMO, a "smart match"
should be able to say, "hmmm, both my operands look like numbers, you know
what, I'll use '==' to compare them!"

Would this be workable:

$a $b Meaning
======= ======= ======================
Any undef ! defined $a
Any ~~-overloaded ~~ overloading is used
~~-ol Any ~~ overloading is used (reversed)
Any CodeRef, &{}-ol $b->($a)
Any Regexp, qr-ol $a =~ $b
Any Looks like number $a == $b (without a "isn't numeric" warning)
Any Simple $a eq $b
Any Any fatal



Abigail


xyf.xiao at gmail

Aug 17, 2012, 6:31 AM

Post #11 of 140 (186 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 5:58 AM, Ricardo Signes
<perl.p5p [at] rjbs>wrote:

>
> ## Core Junctions
>
> Well, that's why we have junctions. Remember those? Of course you do,
> they're
> fantastic.
>
> if ($x ~~ any( qw( John Paul Ringo ) )) {
> tune_strings;
> } else {
> tap_drumps;
> }
>
> We already have very nice junctions in Perl6::Junction. We bring that
> into the
> core (with a new name) and we get nice useful ways to put tests together.
> We
> also get them anywhere else we want them. For me, that's "all over the
> place."
> I bet it will be for lots of other people, too.
>
>
> --
> rjbs
>

As I know, there are many perl programmers who use *List::MoreUtils
*any/all/none/
instead of Perl6::Junction. * *


bmb at mail

Aug 17, 2012, 8:35 AM

Post #12 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On 8/16/12, Ricardo Signes <perl.p5p [at] rjbs> wrote:

> if ($x ~~ any( qw( John Paul Ringo ) )) {
> tune_strings;
> } else {
> tap_drumps;
> }

You're just checking if we're paying attention, right? :-)

--
Brad


perl.p5p at rjbs

Aug 17, 2012, 8:49 AM

Post #13 of 140 (187 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

* Brad Baxter <bmb [at] mail> [2012-08-17T11:35:24]
> On 8/16/12, Ricardo Signes <perl.p5p [at] rjbs> wrote:
>
> > if ($x ~~ any( qw( John Paul Ringo ) )) {
> > tune_strings;
> > } else {
> > tap_drumps;
> > }
>
> You're just checking if we're paying attention, right? :-)

Yes, good job!

--
rjbs
Attachments: signature.asc (0.48 KB)


chris at prather

Aug 17, 2012, 9:37 AM

Post #14 of 140 (187 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 11:49 AM, Ricardo Signes
<perl.p5p [at] rjbs> wrote:
> * Brad Baxter <bmb [at] mail> [2012-08-17T11:35:24]
>> On 8/16/12, Ricardo Signes <perl.p5p [at] rjbs> wrote:
>>
>> > if ($x ~~ any( qw( John Paul Ringo ) )) {
>> > tune_strings;
>> > } else {
>> > tap_drumps;
>> > }
>>
>> You're just checking if we're paying attention, right? :-)
>
> Yes, good job!

It's a little known fact that George Harrison was an excellent drumper.

-Chris


doy at tozt

Aug 17, 2012, 5:42 PM

Post #15 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 03:24:10PM +0200, Abigail wrote:
> On Thu, Aug 16, 2012 at 05:58:16PM -0400, Ricardo Signes wrote:
> >
> > So, last year I said "we really ought to cut most of smart match away."
> >
> > http://www.nntp.perl.org/group/perl.perl5.porters/2011/07/msg174272.html
> >
> > I've slept on it about 380 times, and I'm still for it. Here's the new plan:
> >
> > ## The New ~~ Operator
> >
> > $a $b Meaning
> > ======= ======= ======================
> > Any undef ! defined $a
> > Any ~~-overloaded ~~ overloading is used
> > ~~-ol Any ~~ overloading is used (reversed)
> > Any CodeRef, &{}-ol $b->($a)
> > Any Regexp, qr-ol $a =~ $b
> > Any Simple $a eq $b
> > Any Any fatal
> >
> > This is a nearly a subset of the current behavior. Here are some major points:
> >
> > (1) This is ordered for the sake of knowing which overload to use first.
> >
> > (2) A simple scalar (non-reference, non-glob, non-vstring) on the rhs is
> > used for stringwise equality. I have not yet seen any convincing argument
> > that we can correctly intuit an eq/== behavior, so we pick one.
>
> For me, one of the few advantages I saw in using ~~ is not having to
> wonder when to use == vs eq vs =~. The above table suggests that
>
> "0.0" ~~ 0
>
> is false, while it's currently true. That bothers me.

On the other hand, it makes a lot more sense to me.

> IMO, a "smart match"
> should be able to say, "hmmm, both my operands look like numbers, you know
> what, I'll use '==' to compare them!"
>
> Would this be workable:
>
> $a $b Meaning
> ======= ======= ======================
> Any undef ! defined $a
> Any ~~-overloaded ~~ overloading is used
> ~~-ol Any ~~ overloading is used (reversed)
> Any CodeRef, &{}-ol $b->($a)
> Any Regexp, qr-ol $a =~ $b
> Any Looks like number $a == $b (without a "isn't numeric" warning)
> Any Simple $a eq $b
> Any Any fatal

Honestly, I really can't see myself actually using any version of
smartmatch that actually has a "looks like number" test like that. It's
just too hard to figure out what is actually going to happen to make it
worthwhile for me to actually try to use.

-doy


perl.p5p at rjbs

Aug 17, 2012, 5:42 PM

Post #16 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

* Abigail <abigail [at] abigail> [2012-08-17T09:24:10]
> For me, one of the few advantages I saw in using ~~ is not having to
> wonder when to use == vs eq vs =~. The above table suggests that
>
> "0.0" ~~ 0
>
> is false, while it's currently true. That bothers me. IMO, a "smart match"
> should be able to say, "hmmm, both my operands look like numbers, you know
> what, I'll use '==' to compare them!"
>
> Would this be workable:
>
> $a $b Meaning
> ======= ======= ======================
> [...]
> Any Looks like number $a == $b (without a "isn't numeric" warning)
> Any Simple $a eq $b
> Any Any fatal
> [...]

This is similar to something Damian suggested, which was == if both $a *and* $b
look_like_number. I think that's less jarring to me, as I think I'd expect
("foo" ~~ "0e0") to fail.

What do you think?

At any rate, I'm not writing off the suggestion, and am going to sleep on it...
fewer than 380 times.

--
rjbs
Attachments: signature.asc (0.48 KB)


doy at tozt

Aug 17, 2012, 6:00 PM

Post #17 of 140 (186 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Thu, Aug 16, 2012 at 05:58:16PM -0400, Ricardo Signes wrote:
>
> So, last year I said "we really ought to cut most of smart match away."
>
> http://www.nntp.perl.org/group/perl.perl5.porters/2011/07/msg174272.html
>
> I've slept on it about 380 times, and I'm still for it. Here's the new plan:

Yay!

> ## The New ~~ Operator
>
> $a $b Meaning
> ======= ======= ======================
> Any undef ! defined $a
> Any ~~-overloaded ~~ overloading is used
> ~~-ol Any ~~ overloading is used (reversed)
> Any CodeRef, &{}-ol $b->($a)
> Any Regexp, qr-ol $a =~ $b
> Any Simple $a eq $b
> Any Any fatal
>
> This is a nearly a subset of the current behavior. Here are some major points:
>
> (1) This is ordered for the sake of knowing which overload to use first.
>
> (2) A simple scalar (non-reference, non-glob, non-vstring) on the rhs is
> used for stringwise equality. I have not yet seen any convincing argument
> that we can correctly intuit an eq/== behavior, so we pick one.
>
> Forcing numeric comparison can be done with things like the helpers found in
> Smart::Match: things to produce a CodeRef that has the correct behavior.
>
> (3) Container types (array, hash) are no longer treated specially. They were
> the most unintuitive case, and they get kicked out. More on that later.

Mostly +1, but I'm still questionable about the ~~-ol/Any case. This
means that I still can't do "$thing ~~ sub { ... }" and get reliable and
predictable behavior. This may be less of an issue if that case was at
the bottom right above Any/Any, but I don't know if that would also make
it less useful for whatever you had in mind for it (where does autodie
use it?).

> This gets is back to what I've always said is the real power of ~~: a
> simple way to provide "a test" to run against a value, where the creator of the
> value know just how it will be used. With one exception, we're dispatching
> entirely based on the rhs, and they're all obvious.
>
> "Oh no!" you may cry, "What about $x~~@opts? All I wanted was an `in`
> operator!"
>
> ## Core Junctions
>
> Well, that's why we have junctions. Remember those? Of course you do, they're
> fantastic.
>
> if ($x ~~ any( qw( John Paul Ringo ) )) {
> tune_strings;
> } else {
> tap_drumps;
> }
>
> We already have very nice junctions in Perl6::Junction. We bring that into the
> core (with a new name) and we get nice useful ways to put tests together. We
> also get them anywhere else we want them. For me, that's "all over the place."
> I bet it will be for lots of other people, too.

Definite +1.

> ## Backcompat and ~~
>
> My anxiety over backward compatibility for ~~ is not gut-wrenching. Still, it
> would be nice to do what we can.
>
> After a lot of talk about making ~~ pluggable across different scopes, I think
> it's a non-starter. It's just not the kind of thing we can plug this way,
> because of the way in which we expect it to be used. If we expect users to
> pass a test from their code to some other code, they need to know how that code
> will use it. It needs to be the same everywhere.
>
> It would be nice to provide a best-effort backcompat with a deprecation warning
> when possible. I'd like to know how good that effort can be. Since the new
> table is in many ways a subset of the old one, I think it can be pretty good.
>
> As previously mentioned, the "switch" feature is considered highly
> experimental; it is subject to change with little notice. In
> particular, both "given" and "when" have tricky behaviours that are
> expected to change to become less tricky in the future. Do not rely
> upon their current (mis)implementations.
> -- perlsyn
>
> ## Fixing given and when
>
> I think we already fixed given pretty hard. I need to look at bit more at it,
> but let's take it as "fixed enough" for now.
>
> when!
>
> Oh, when, how you trouble me.
>
> I propose that `when(X)` *always* means `$_ ~~ X`. All of the special cases
> for parsing and interpreting the inside of when can go. They can all be
> reduced to `when(sub{...})`. I would also smile upon `when({...})` acting as a
> test block. (Since you can't put a hashref on the rhs of ~~ anymore, there is
> no ambiguity.)

I like the concept, but "when ({ ... })" reads kind of weird. Everywhere
else in the language, ({ ... }) means a hashref - anything that means a
block has some kind of leading keyword inside any potential parentheses:
"(do { ... })", "(sub { ... })", etc. I think just leaving it as
"when (sub { ... })" is probably going to be the least confusing.

> The exceptions (from perlsyn's "Experimental Details on given and when") are:
>
> EXCEPTION WAS IS NOW
> 1. subroutine call -- when (foo())) -- when ({ foo() })
> 2. regex match -- when ( /foo/ ) -- when (qr/foo/)
> -- when ( $_ !~ /foo/) -- when ( none( qr/foo/ ) )
> 3. smart match -- when ($a ~~ $b) -- when ({ $a ~~ $b })
> 4. comparison -- when ($a lt $b) -- when ({ $a lt $b })
> 5. some builtins -- when (eof) -- when ({ eof })
> 6. negation -- when (! $x) -- when ({ ! $x })
> 7. bool filetest -- when (-r) -- when ({ -r })
> 8. flip flops -- when ($a .. $b) -- when ({ $a .. $b })
> 9. conjunction -- when ($a && $b) -- when ( all( $a, $b ) )
> or when ({ $a && $b })
> 0. disjunction -- when ($a || $b) -- when ( any( $a, $b ) )
> or when ({ $a || $b })
>
> Also, `when` should be valid inside an auto-topicalizing `while`, providing an
> implicit next, making its behavior more generic so that `when` can be used
> safely everywhere that it makes sense.

+1

> ## In Conclusion
>
> I think this makes ~~ and given/when both totally predictable. I've gone over
> this design quite a bit, and I think it turns these features from a liability
> to an asset. I also think that we'll be able to eliminate quite a lot of
> documentation, which I take as a very good sign. (A lot of that documentation
> includes things like "this part is really hard to understand.")
>
> When ~~ works like this, I will use it all the time.

-doy


abigail at abigail

Aug 18, 2012, 5:31 AM

Post #18 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 08:00:25PM -0500, Jesse Luehrs wrote:
>
> I like the concept, but "when ({ ... })" reads kind of weird. Everywhere
> else in the language, ({ ... }) means a hashref - anything that means a
> block has some kind of leading keyword inside any potential parentheses:
> "(do { ... })", "(sub { ... })", etc. I think just leaving it as
> "when (sub { ... })" is probably going to be the least confusing.


Maybe that ought to be fixed ;-). After reading your statement, I tried:

$ perl -wE 'sub foo (&) {say $_ [0] -> ()} foo ({1})'
Type of arg 1 to main::foo must be block or sub {} (not anonymous hash ({})) at -e line 1, near "})
"
Execution of -e aborted due to compilation errors.
$

I was surprised the parens are not allowed in this case.



Abigail


abigail at abigail

Aug 18, 2012, 5:38 AM

Post #19 of 140 (188 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Fri, Aug 17, 2012 at 08:42:35PM -0400, Ricardo Signes wrote:
> * Abigail <abigail [at] abigail> [2012-08-17T09:24:10]
> > For me, one of the few advantages I saw in using ~~ is not having to
> > wonder when to use == vs eq vs =~. The above table suggests that
> >
> > "0.0" ~~ 0
> >
> > is false, while it's currently true. That bothers me. IMO, a "smart match"
> > should be able to say, "hmmm, both my operands look like numbers, you know
> > what, I'll use '==' to compare them!"
> >
> > Would this be workable:
> >
> > $a $b Meaning
> > ======= ======= ======================
> > [...]
> > Any Looks like number $a == $b (without a "isn't numeric" warning)
> > Any Simple $a eq $b
> > Any Any fatal
> > [...]
>
> This is similar to something Damian suggested, which was == if both $a *and* $b
> look_like_number. I think that's less jarring to me, as I think I'd expect
> ("foo" ~~ "0e0") to fail.
>
> What do you think?


Yeah, I initially wanted to propose (LLN == looks like a number):

LLN LLN $a == $b
!LLN LLN false
LLN !LLN false

and then thought "ah, but the last two are redundant, they will fall back
to 'eq', and that will return false anyway". And then I returned the remaining
case into 'Any LLN', forgetting about the oddity that when something doesn't
look a like a number, we treat it as 0.

So, yeah, Damian is right, '==' should be used iff both sides look like
numbers. That was my intention as well, but there were some bad transmissions
errors between my brain and the email that I send.



Abigail


ikegami at adaelis

Aug 18, 2012, 6:51 AM

Post #20 of 140 (187 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Thu, Aug 16, 2012 at 5:58 PM, Ricardo Signes
<perl.p5p [at] rjbs>wrote:

> ## Backcompat and ~~
>
[...]

> As previously mentioned, the "switch" feature is considered highly
> experimental; it is subject to change with little notice. In
> particular, both "given" and "when" have tricky behaviours that are
> expected to change to become less tricky in the future. Do not rely
> upon their current (mis)implementations.
> -- perlsyn
>

"~~" is not part of the "switch" feature. That paragraph is not relevant.
There's absolutely no mention of "~~" being considered experimental in its
5.16.0 docs!


sprout at cpan

Aug 19, 2012, 12:16 PM

Post #21 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

rjbs wrote:
> Also, `when` should be valid inside an auto-topicalizing `while`, providing an
> implicit next, making its behavior more generic so that `when` can be used
> safely everywhere that it makes sense.

Please keep

while(<>)

and

while(defined($_ = <>))

equivalent.

Otherwise while<> would have to be deparsed as while<>, removing a useful feature of Deparse (finding out how perl is interpreting the while).

What do you want to do about this?

$ perl -E 'given(1) { for my $x (2) { break } } warn ok'
ok at -e line 1.
$ perl -E 'given(1) { for (2) { break } }'
Can't "break" in a loop topicalizer at -e line 1.

I think the best solution is to make when (and default) always do an implicit next. Also make given respond to next and last, just like a bare block. Deprecate break, but make it consistently exit the innermost given, without complaining about intervening frames.


damian at conway

Aug 19, 2012, 2:42 PM

Post #22 of 140 (185 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

I must say I was very uncertain when Rick first talked with me about
this proposed second attempt to fix smartmatching. But having talked
with him at length about the issue during OSCON, I am now in strong
agreement that this proposal represents a genuine 'fix', rather than
just yet another unnecessary change.

The current smartmatching table, with its 23 cases, is simply far too
complex for real humans to handle. And the fact that there are a further
8 exceptions for smartmatching inside a 'when' (and not just exceptions
to the table, but exceptions to standard Perl semantics as well) makes
the entire feature more-or-less unusable for most people.

The new proposal has only six smartmatching cases and only one special
syntax for 'when' (of which, more below). I think that might make
smartmatching sufficiently predictable and usable for the vast majority of Perl
developers to consider it a viable tool.

And the addition of:

use junctions;

(or whatever) to the core would have enormous benefits beyond just
smartmatching.

My main concern was always the removal of all the hash- and array-based
cases, but in thinking about that I eventually realized that I couldn't
actually remember them all myself. And that I wasn't even sure about
most of ones that I could remember, except for @ARRAY~~@ARRAY
and $ANY~~@ARRAY.

For example, I know there's a table entry for %HASH~~@ARRAY,
but I'm not sure whether the meaning of that is:

any( keys %HASH) ~~ any(@ARRAY)
any(values %HASH) ~~ any(@ARRAY)
all( keys %HASH) ~~ any(@ARRAY)
all(values %HASH) ~~ any(@ARRAY)
any( keys %HASH) ~~ all(@ARRAY)
any(values %HASH) ~~ all(@ARRAY)

Moreover, I'm not even sure whether @ARRAY~~%HASH
does the same thing as %HASH~~@ARRAY.

The point being, that all of the above junction-based versions are
perfectly clear to me, and were easy to get right in the first place.
And the current smartmatching table doesn't even offer 5/6 of them.

My point is that if even the original proponent of smartmatching can't
use it without RTFM-ing, how can we consider the current arrangement
anything but broken? And how can reducing the current table+special cases
from 31 to 7 be anything but a vast improvement?

My one point of disagreement with Rick's current proposal is that,
like Abigail, I feel it's essential for smartmatching (and hence 'when')
to handle matching numbers sensibly. And by sensibly, I mean "not with eq".

A simple failure-case I have already mentioned privately to Rick is this:

while (readline) {
when (undef) { say 'done'; last; }
when (0) { say 'must be +ve'; }
when (any 1..9) { say 'digit'; }
default { die 'horribly'; }
}

...which dies horribly even when a single digit is correctly typed in.

The behaviour I proposed instead was that the full table should be:

$a $b Meaning
======= ======= ======================
Any undef ! defined $a
Any ~~-overloaded ~~ overloading is used
~~-ol Any ~~ overloading is used (reversed)
Any CodeRef, &{}-ol $b->($a)
Any Regexp, qr-ol $a =~ $b
Any Simple looks_like_num($a) && looks_like_num($b)
? $a == $b
: $a eq $b
Any Any fatal

That is, exactly the same table as Rick proposes, except that a smartmatch
between two simple scalars that could reasonably be considered numbers
will actually use numeric matching.

As regards the 'when' reboot, anything we can do to get rid of those eight
special cases--which don't behave like anything else in Perl 5--would be
a blessing.

And for that very reason (avoiding one-off special syntax and semantics),
I also think that the new block syntax for 'when' should be:

when {CODE} {...}

not:

when ({ CODE }) {...}

because everywhere else that Perl uses a raw block as a thunk
(e.g. 'map', 'grep', 'sort'), the opening curly can come immediately
after the keyword, no parens required. And, given that anonymous
hashes would no longer be allowed as arguments to 'when', there's no
possible ambiguity without the parens.

In contrast, a set of curlys is *never* a block when it's the only thing in a
set of parens...it's always a hash constructor). It would be far better to keep
it that way, than to add a new syntactic special case just for 'when'.

Anyway (FWIW, and with that one caveat about numeric matching)
I just wanted to say that I'm fully in favour of this proposed fix,
despite the hassle of breaking backwards compatibility (again).

Damian


sprout at cpan

Aug 19, 2012, 5:44 PM

Post #23 of 140 (184 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

Damian Conway probably regrets writing:
> In contrast, a set of curlys is *never* a block when it's the only thing in a
> set of parens...it's always a hash constructor).

Heeheehee.

I just fixed this in bleadperl:

format =
@*
({ "Just another Perl hacker, " })
.
write


jvromans at squirrel

Aug 20, 2012, 5:44 AM

Post #24 of 140 (162 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

Damian Conway <damian [at] conway> writes:

> A simple failure-case I have already mentioned privately to Rick is this:
>
> while (readline) {
> when (undef) { say 'done'; last; }
> when (0) { say 'must be +ve'; }
> when (any 1..9) { say 'digit'; }
> default { die 'horribly'; }
> }
>
> ...which dies horribly even when a single digit is correctly typed in.

I assume this is because of the trailing newline?
If so, I think it should die. "1" is not equal to "1\n" even though atoi
fans will claim so.

-- Johan


doy at tozt

Aug 20, 2012, 5:45 AM

Post #25 of 140 (162 views)
Permalink
Re: fixing smartmatch just hard enough (and when, too) [In reply to]

On Thu, Aug 16, 2012 at 05:58:16PM -0400, Ricardo Signes wrote:
> Also, `when` should be valid inside an auto-topicalizing `while`, providing an
> implicit next, making its behavior more generic so that `when` can be used
> safely everywhere that it makes sense.

One other thing - why do we limit the use of 'when' like this at all? Is
there any reason we can't just say that when always does an implicit
next regardless of where it's used, and so any time you're in a context
where 'next' makes sense (which is really most places), 'when' would
also work? For instance:

$_ = "foo";
{
when (/f/) { ... }
when (/a/) { ... }
}

Is there any reason that something like that wouldn't have well-defined
semantics?

-doy

First page Previous page 1 2 3 4 5 6 Next page Last page  View All Perl porters RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.