develooper Front page | perl.perl5.porters | Postings from November 2017

Re: Revisiting smart match

Thread Previous | Thread Next
From:
Zefram
Date:
November 27, 2017 18:11
Subject:
Re: Revisiting smart match
Message ID:
20171127181119.GI4913@fysh.org
Ricardo Signes wrote:
>I've thought of the rhs of a smart match as best being a stand-in for a
>predicate function.  given/when is explicitly performing tests at each branch,
>so I'm not sure we're doing the right thing to just evaluate a when's
>condition as a boolean expression.

This makes sense.  The premise is if anything enhanced by the
stripped-down form of smartmatch, and this is a decent reason to have
a short syntax for smartmatching in "when".  I have no objection to
such existing.

But, firstly, it isn't strong enough reason to give up having a short
syntax for ad hoc truth-value expressions.  Encouraging the use of
matchers is fine, but from time to time we're always going to need a
completely custom kind of criterion that is best expressed by inline code
at the point of the "when".  Your example didn't include anything really
requiring this treatment; think more along the lines of my example "$_
eq 'foo' && $have_gripley".  This *can* be formulated as a matcher like
"mstr('foo') & anything_or_nothing($have_gripley)", or "$have_gripley
? mstr('foo') : Nothing".  But it's easier to think about in the form
of the original expression, and this difference gets more pronounced as
the complexity of the logic grows.

Of course there's more than one way to handle inline truth-value code.
It could still be wrapped up as a matcher, something like "satisfies(sub
{ $_[0] eq 'foo' && $have_gripley })".  But that's still forcing us
to think in terms of a predicate applied to $_, it has quite a lot of
verbiage, and (as I mentioned earlier) it incurs a bunch of sub call
overhead that would often enough be a problem.  So a syntax for "when"
to directly take a truth-value expression gives us a valuable mental,
syntactic, and semantic shortcut.  A good matcher ecosystem can minimise
the demand for this, but the minimum demand is still significant and
needs to be satisfied.

So we'll probably converge on having short syntax for both.  Taking that
as read, we merely have to decide how to spell them.  Welcome to the
bikeshed.

The only example you gave of having short syntax for both was the older
idea, via FC, of "when()" for smartmatch and "when{}" for truth value.
The use of braces is problematic.  Historically, this idea actually arose
as syntactic sugar for a "when(satisfies(sub {...}))" type of construct.
If it's interpreted that way, the braces delimit a code block rather than
merely an expression, we have all the overhead of constructing a matcher
object and calling a couple of layers of subroutine, and we have all the
semantic baggage of a sub call, imposed in a context that doesn't look
like an independent subroutine.  Supposing we drop the actual matcher
object and subroutine calls, we still have an unappealing choice: do the
braces make a code block (containing a statement sequence)?  If yes, this
is still some surprising baggage.  If no, so the braces just enclose an
expression, this is surprisingly unlike braces elsewhere in the grammar,
which usually make code blocks.  And any way round we have the rather
unusual "} {" which fails to look connected.

To avoid the connotations of braces, the options for the immediate
delimiters of the expression are really just parens or square brackets.
(We do need full delimitation.  The Perl 6 style of an expression being
followed by an open brace would introduce horrendous new ambiguities
that Perl 6 was specifically designed to avoid.)  If the immediate
delimiters that we pick are the same for both, then we can distinguish
them by the presence of some additional character, probably before the
opening delimiter.  In that case, which one requires an extra mark is
relevant to Huffman coding.

The syntax that I have suggested is "when()" for truth value and "when~()"
for smartmatch.  In that form, your example would look like

    given ($input) {
        when ($_ eq "string") { die "A" }
        when ($_ == 90210)    { die "B" }
        when ~($matcher)      { die "C" }
    }

though for such common types of conditions, as discussed above, it might
still be more idiomatic to use your mstr() and mnum() to construct matcher
objects.  Anyway, the example serves to show how these two flavours of
"when" look together, and I'm pretty happy with how they look there.

Another option that I've previously suggested is "when()" for truth
value and "when[]" for smartmatch.  The crowd who found the square
signatures proposal horrendously ugly would probably object; I'd take
their aesthetic issues with a pinch of salt.  (Seriously, what's wrong
with square brackets?  Don't you use arrays?)

In both of these proposals, I've favoured "when()" for truth value
expressions in order to parallel "if()".  That's not essential, but
it's a standard that's worth applying if we don't have a strong reason
to do otherwise.  The obvious strong reason to do otherwise would be
Huffman coding, if we reckon smartmatching would be (or should be) much
more common than truth value expressions.  That may well be the case;
I wasn't thinking about the Huffman coding when I proposed "when~()".
So if we go that way, we'd have "when()" for smartmatching and probably
"when?()" for truth value.  Your example would then look like

    given ($input) {
        when ?($_ eq "string") { die "A" }
        when ?($_ == 90210)    { die "B" }
        when ($matcher)        { die "C" }
    }

which also looks fine to me.

Finally, having specific syntax for both forms of "when" raises the
question of what postfix "when" should do.  It doesn't have mandatory
bracketing of the condition operand, so we can't just make a parallel
change to its syntax.  We could have postfix "when" always do smartmatch,
or always take a truth value, or become different from all other
postfix modifiers by requiring bracketing of the condition expression,
or be abolished.  I have no real preference between these, except that
if we're Huffman coding the prefix "when" forms then a fixed choice of
semantic for postfix "when" should probably match whatever got the shorter
"when()" syntax.

-zefram

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About