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

Re: Revisiting smart match

Thread Previous | Thread Next
From:
Eirik Berg Hanssen
Date:
November 27, 2017 18:38
Subject:
Re: Revisiting smart match
Message ID:
CAHAeAG7YkVYEUdiGndWuqJNfCcxk-xDa6Bd3p9cgDEcqKTKVyA@mail.gmail.com
On Mon, Nov 27, 2017 at 7:11 PM, Zefram <zefram@fysh.org> wrote:

> 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.
>

  This final issue presumes that the bracketing determines which construct
we're dealing with.

  This voice from the peanut gallery would like to know if the two
different constructs could use two different keywords, or if that
particular shade has been ruled out for this bikeshed?

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

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

  (... or vice-versa, if that reads better - or hey, whatever reads better
...)

  Having two such related-but-different constructs share the same keyword,
seems to me a mismanagement of cognitive load.  But then, I'm no language
designer ...


Eirik

<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Virus-free.
www.avg.com
<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

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