Front page | perl.perl5.porters |
Postings from November 2017
Re: Revisiting smart match
November 24, 2017 13:45
Re: Revisiting smart match
Message ID: 20171124134507.GF4913@fysh.org
Leon Timmermans wrote:
>What do you mean exactly with implicit enreferencement?
I mean this transformation:
$ perl -MO=Deparse -E 'print @a ~~ %a' |& grep print
print \@a ~~ \%a;
If an array or hash is mentioned as either operand of smartmatch, or
as the argument to "when" or "given", then the operand is implicitly
transformed into *a reference to* that array or hash. Otherwise the
operand just goes into scalar context in the ordinary manner. Implicit
enreferencement would have been fine behaviour for arrays and hashes
in scalar context, if it had been in the language from the start, but
with the smartmatch-related ops being the only ones doing it it's just
an exception to otherwise-consistent language semantics.
Additionally, the smartmatch operator, but not "when" or "given",
implicitly transforms a regexp match op "/foo/" into a regexp compilation
op "qr/foo/". A code comment describes this as "tak[ing] a reference"
to the regexp, but since "\/foo/" doesn't have the same effect that's
a dubious way of describing it. Anyway, I was counting that as part of
the same phenomenon; my branch doesn't do it.
The documentation isn't clear on these semantics. It speaks of implicit
*de*referencement, but also of scalar context, and, well, it's a mess.
This is the documentation that literally says its subject "is hard to
>> * when() never implicitly smartmatches, only uses arg as truth value
>This doesn't really make sense to me: why would anyone want to use this?
Apparently people wanted non-smartmatch conditions enough to make "when"
attempt to guess what they meant. perlsyn(1) has a long list of types
of condition expression that will be treated as truth values rather
than matchers. It may be a specific type of comparison such as "$_ == 0"
that's not readily expressed as a smartmatch. It may be a parameterised
predicate sub call such as "is_gronkable($_, 'foo', $context)". It may
be a combination of conditions not all using $_, such as "$_ eq 'foo'
All of these conditions can in principle be formulated as smartmatch
objects to be applied to $_, but in the general case doing so amounts to
creating a closure containing the arbitrary code and wrapping that up as
a smartmatcher. It's not always going to be convenient, and sometimes
doing it would obscure the logic actually at work. It's also slower if
it has to be done as a closure rather than just executing the couple of
ops, and given/when structures are often going to be quite hot.
So there's good cause for "when" to support ordinary truth-value
conditions. Given that it does support that, there's no actual need
for shorter syntax for smartmatching; that's at most a nice-to-have.
>Breaking code with the idea "maybe we will unbreak it, but not before
>you've suffered the pain" sounds unnecessarily cruel.
To be clear, I was proposing a short syntax for "when" smartmatching that
is different from the current syntax, so that wouldn't be unbreaking
something previously broken. There are some other things that could
potentially be added back with their former syntax, but they're all
things that smartmatch doesn't need, and I reckon they're not pulling
their weight. We'll certainly learn more from trying smartmatch without
them than we would from keeping that weight in.
It is true that this change will break most existing code that uses
smartmatch. But that's true of any radical simplification of the feature,
and a radical simplification is necessary in order to achieve a feature
that we're comfortable with.