From: Klaus on
On 28 juil, 10:48, "Peter J. Holzer" <hjp-usen...(a)hjp.at> wrote:
> On 2010-07-28 07:03, Klaus <klau...(a)gmail.com> wrote:
>
> > On 24 juil, 08:38, Ilya Zakharevich <nospam-ab...(a)ilyaz.org> wrote:
> >> On 2010-07-23, jl_p...(a)hotmail.com <jl_p...(a)hotmail.com> wrote:
>
> >> >    I find this a bit counter-intuitive.
>
> >> There is nothing "a bit counter-intuitive" about the smart matching
> >> operation.  It is just *absolutely useless*, since there is no
> >> humanly-possible way to predict what it would do.
>
> > I perfectly agree.
>
> I haven't tried to use it in anger yet (as mentioned in another posting,
> I have still too many machines running 5.8.x), but from reading the docs
> I tend to agree: It's way too complicated and I don't think I can
> remember that stuff. It is of course possible that those rules exactly
> match my intuition, but somehow I doubt it.
>
> > Another feature in smart matching that is counter-intuitive/useless
> > where there is no humanly possible way to predict what it would do is:
>
> > the rule that if the lefthand side of a smartmatch is a number and the
> > righthand side is a string that *looks like a number*, then that
> > string is treated like a number.
>
> > First of all, it is impossible in Perl 5 (due to dualvars) to see
> > whether or not a variable contains a number or not.
>
> Right.
>
> > Secondly, the rule whether or not a string looks like a number is not
> > straight forward:
>
> What's not straightforward about that? Except maybe for leading and
> trailing whitespace the results are what I expected.

Agreed, the rule as such whether or not a string looks like a number
is straight forward.

However, what trips me up with smartmatching is the combination of
numbers on the lefthand side combined with what looks like a number on
the righthand side.

Here is my (admittedly contrived) example:

******************************
use strict;
use warnings;
use 5.010;

my $val = ' 3';

checkvalue($val);

my $formatted = sprintf '%6.2f', $val;

checkvalue($val);

sub checkvalue {
if ($_[0] ~~ '3') { say "there is no space"; }
elsif ($_[0] ~~ ' 3') { say "there is one space"; }
elsif ($_[0] ~~ ' 3') { say "there are two spaces"; }
elsif ($_[0] ~~ ' 3') { say "there are three spaces"; }
else { say "I don't know what to say..."; }
}
******************************

Here is the output:
******************************
there are two spaces
there is no space
******************************

(please note that for exactly the same subroutine call
checkvalue($val); we get different output, depending on whether $val
has been part of an sprintf-call or not)

The thing that annoys me here is that each time I use smartmatches
with stringliterals on the righthand side, I always have to think
whether or not the string looks like a number. (in which case I should
better use the old "eq" instead of "~~")

Which leads me to the conclusion that I better should use the old "eq"
in all cases --> that also includes cases like $val ~~ ['3', ' 3', '
3', ' 3'] --> that would also better be written as $val eq '3' or
$val eq ' 3' or $val eq ' 3' or $val eq ' 3'.

Final verdict: Smartmatching works as expected in 99.9999% of all
cases. If you are concerned about 0.00001% of the cases (such as $val
~~ ['3', ' 3', ' 3', ' 3']), then better stick with the old "eq"
and let others debug their own smartmatching code.

--
Klaus
From: Ilya Zakharevich on
On 2010-07-27, Ben Morrow <ben(a)morrow.me.uk> wrote:
> Smartmatch semantics changed in several small but important ways between
> 5.10.0 and 5.10.1. I would highly recommend avoiding smartmatch on
> 5.10.0 for this reason. (I believe the intention is not to change them
> again.)

I strongly hope that this intention will be violated. *THERE IS* a
way to salvage smart match - but it must be made non-backward
compatible.

E.g., consider the following scenario:

a) Choose a small number N (I favor 3 ;-).

b) Write N simple rules explaining what ~~ should do (and "simple"
means AT LEAST having no "...except for...").

c) Add new `use strict' type 'smartmatch', enabled by default.

d) In scope of `use strict "smartmatch"', force ~~ to die() if it
encounters something not covered by (b), or when more than one
rule in (b) is applicable, and results conflict.

And I'm pretty sure that there must be yet smarter fixes...

Yours,
Ilya
From: Klaus on
> However, what trips me up with smartmatching is the combination of
> numbers on the lefthand side combined with what looks like a number on
> the righthand side.
>
> Here is my (admittedly contrived) example:
>
> ******************************
> use strict;
> use warnings;
> use 5.010;
>
> my $val = '  3';
>
> checkvalue($val);
>
> my $formatted = sprintf '%6.2f', $val;
>
> checkvalue($val);
>
> sub checkvalue {
>     if    ($_[0] ~~    '3') { say "there is no space";           }
>     elsif ($_[0] ~~   ' 3') { say "there is one space";          }
>     elsif ($_[0] ~~  '  3') { say "there are two spaces";        }
>     elsif ($_[0] ~~ '   3') { say "there are three spaces";      }
>     else                    { say "I don't know what to say..."; }}

One possible solution is to always quote the lefthand side of a
smartmatch

sub checkvalue {
if ("$_[0]" ~~ '3') { say "there is no space"; }
elsif ("$_[0]" ~~ ' 3') { say "there is one space"; }
elsif ("$_[0]" ~~ ' 3') { say "there are two spaces"; }
elsif ("$_[0]" ~~ ' 3') { say "there are three spaces"; }
else { say "I don't know what to say..."; }}

This works, but I don't think it is a good solution in the light of
perlfaq4 - What's wrong with always quoting "$vars"?

--
Klaus