Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:109640
Return-Path: <tovilo.ilija@gmail.com>
Delivered-To: mailing list internals@lists.php.net
Received: (qmail 51749 invoked from network); 14 Apr 2020 18:54:00 -0000
Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5)
  by pb1.pair.com with SMTP; 14 Apr 2020 18:54:00 -0000
Received: from php-smtp4.php.net (localhost [127.0.0.1])
	by php-smtp4.php.net (Postfix) with ESMTP id 76E0A1804C2
	for <internals@lists.php.net>; Tue, 14 Apr 2020 10:23:41 -0700 (PDT)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net
X-Spam-Level: 
X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,
	DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,
	RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS
	autolearn=no autolearn_force=no version=3.4.2
X-Spam-ASN: AS15169 209.85.128.0/17
X-Spam-Virus: No
X-Envelope-From: <tovilo.ilija@gmail.com>
Received: from mail-yb1-f173.google.com (mail-yb1-f173.google.com [209.85.219.173])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256)
	(No client certificate requested)
	by php-smtp4.php.net (Postfix) with ESMTPS
	for <internals@lists.php.net>; Tue, 14 Apr 2020 10:23:40 -0700 (PDT)
Received: by mail-yb1-f173.google.com with SMTP id i2so7617816ybk.2
        for <internals@lists.php.net>; Tue, 14 Apr 2020 10:23:40 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=mime-version:references:in-reply-to:from:date:message-id:subject:to
         :cc;
        bh=gGqR9t8BheKCnuDluAZfW4eUyi+wdVKymHCKYp/rYG8=;
        b=jUkNPvXSkog4ujJymCalPU1m0e6RbAxP7Y5xxHM/TFSFjQ7jJRGlbULPdzjEhIY7C4
         LLciqH/jnsgGtbPCzHod9fWkEkdymekv5hNLWE7ozlskWyR0nlr4mcBEqU26w+uQxg9k
         StbI3KDlH2VC2gYNYggBxN9YPyHamKRiZP93WjuydqUc+ylbV9pknZnGmZfjHh2kNMCD
         W0H6wrfJrAULhOA1l9LPmD/wK+7bwUEN7AHGW84ahF2tcUzJnpNoOjHolsKQqVEU8wHn
         S1mF6R+TT11hMo10izlWP0YZJxGtbtT9XHvsAMCwIVDePnD65jk9TrOC3NPF2oLivzIy
         IJSA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:mime-version:references:in-reply-to:from:date
         :message-id:subject:to:cc;
        bh=gGqR9t8BheKCnuDluAZfW4eUyi+wdVKymHCKYp/rYG8=;
        b=P5RZyvtQC1cyNrOJVW30K/n4vmQSvoWCRoQJ4iGg/qlTSXHATqAXzFXhUXLsW16IWQ
         XZoQ21Gy+5w5uASLJ+x3p2ijR9lX1VpOh34hiMVNus3C+1OgXjaumbIKdZX43Ij6KZmz
         WtHNLrnWIsgW0IBcxptz1JsOycem1nwg5/PKrVb0PCRvwsaiNoPlFhP/Q8qGsyMvXjMZ
         Wxw/wGwfgJ43i3W61v8fx0RtG3POwcwmla4+V8ZWk0cjqG+h+yvRRWAiYloycJ6cuIUo
         a2G2n071p7sODpJrH9fgP2+nIvA6+jGwTHgbDYVR6aWmfM0lYyR6llug/iOzWkCkh/fR
         ZZOg==
X-Gm-Message-State: AGi0PuaqBx26AVRf8kMFRbeQWUiFQ9dKlbhg0FyGzSUTpaxKd1HkDaUX
	eKXyeb2YfsIvxVDSJ9qsybTV/z78wM+iaIZTkCM=
X-Google-Smtp-Source: APiQypLIuEAUqU+kBowosiCYywl3PtwRPjS4NWTenWiMY5jMs/px+Cwdbt8tqBWttBTTduTQU9J9q0rBAh3ZTsUniNs=
X-Received: by 2002:a25:5f07:: with SMTP id t7mr1615616ybb.411.1586885019237;
 Tue, 14 Apr 2020 10:23:39 -0700 (PDT)
MIME-Version: 1.0
References: <CAPyj-LDfdATXFD+dc5AY9EqWWxgf8LP1joD2fzvm==1gUoN35A@mail.gmail.com>
 <5e94f84b.1c69fb81.8f1da.317bSMTPIN_ADDED_MISSING@mx.google.com>
In-Reply-To: <5e94f84b.1c69fb81.8f1da.317bSMTPIN_ADDED_MISSING@mx.google.com>
Date: Tue, 14 Apr 2020 19:23:27 +0200
Message-ID: <CAPyj-LBOxBmeaVGWZ5+C5cQhFw4QDW7cQD_c5PRKU39eRLy99Q@mail.gmail.com>
To: Andrea Faulds <ajf@ajf.me>
Cc: PHP internals <internals@lists.php.net>
Content-Type: text/plain; charset="UTF-8"
Subject: Re: [PHP-DEV] Re: [DISCUSSION] Match expression
From: tovilo.ilija@gmail.com (Ilija Tovilo)

Hi Andrea

I realize there's a lot of noise in the mailing list right now, I'll
keep this my only e-mail for today.

> I share others' concern that it is inconsistent with PHP's
> existing statements

Can you elaborate on what exactly the concerns are? Note that even if
we added block expressions to the language there are still certain
sanity checks we'd likely need to make, so the differentiation between
statement/expression would still not go away. For example:

```
match ($y) {
    1 => {
        echo 'Foo';
        echo 'Bar';
        // This is fine
    },
}

$x = match ($y) {
    1 => {
        echo 'Foo';
        echo 'Bar';
        // Error, block must return a value.
    },
};
```

At the moment there are very limited use cases for the block
expression. The only ones I can think of are the match expression,
arrow functions and maybe normal functions. And as that would
introduce two ways to return a value from a function it's questionable
whether we should even allow that or not.

```
$arrowFn = fn() => {
    echo 'Foo';
    'Bar'
};

// Questionable. You're saving a few characters
function getFoo() {
    echo 'Foo';
    $this->foo
}
```

> It is a shame you don't suggest taking this opportunity to add
> pattern matching.

My main concern here is just complexity. There's so much to consider.
We need to think well about each pattern, how it should work, what it
should look like, how it should be implemented, etc. Furthermore
pattern matching usually isn't restricted to the match expression.
There's often pattern matching for `if`, `while`, `foreach`, function
params, normal assignment, etc. So I don't think it should be mixed
with this RFC. IMO if we implement pattern matching we should make it
available for all of these cases.

```
let [string $x, 10] = ['foo', 20]; // Error: Unmatched pattern

if (let Foo { bar: $bar } = $foo) {}

while (let 1..<10 = $x) {}
```

> Using a keyword prefix (e.g. `let`) in future means we end
> up with two kinds of arm (one with === behaviour, one with
> pattern-matching behaviour), but wouldn't it be simpler to
> have just one?

I personally don't think so. Consider this case:

```
$x = 10;
$y = 20; // This variable is unused

match ($x) {
   $y => { // Always true
      echo $y; // Outputs 10
   },
}
```

`$y` is an identifier pattern and it always matches and assigns the
given value to the variable. This is rather confusing. A keyword like
`let` would make it more obvious that you're using a pattern. I'd also
suspect that it's more common to pass expressions to the lhs of a
match statement than patterns so it makes sense that this is the
default.

Also, imagine you want to equate multiple dynamic values with each other:

```
$x = ...;
$y = ...;
$z = ...;

match ($x) {
    $y => ...,
    $z => ...,
}

// If we only have pattern matching
match (true) {
    true if $x === $y => ...,
    true if $x === $z => ...,
}
```

Without allowing dynamic lhs expressions this becomes pretty awkward.

> Relatedly, it is a shame not to have guards

I don't think guards are awfully useful without pattern matching.
What's the benefit over this?

```
match ($x) {
    1 => {
        if ($foo === BAR) {
            ...
        } else {
            ...
        }
    },
}

// vs

match ($x) {
    1 if $foo === 'Bar' => {
        ...
    },
    1 => {
        ...
    },
}
```

That just makes it harder to generate a jump table. It does reduce
nesting a bit but the same could be said for if statements in loops
where we don't have guards.

> It is unfortunate if we have to add another reserved word

My previous draft was mainly criticized because of the usage of the
`switch` keyword.

Ilija