On Fri, Sep 8, 2023, at 10:16 PM, Ilija Tovilo wrote:
> Hello everyone
>
> I've been working on match blocks over the last few weeks.
> https://wiki.php.net/rfc/match_blocks
>
> I've already shared it in R11 and got conflicting feedback, which
> makes me unsure on how to proceed. We have a few options.
>
> 1. Add blocks only to match, possibly adding blocks to other
> constructs in separate RFCs (the approach of this RFC)
> 2. Support block expressions as a language-level concept, analogous to
> https://doc.rust-lang.org/reference/expressions/block-expr.html
> 3. Do nothing
>
> The two main complaints/questions I've gotten was whether this
> approach is the right one, and whether the syntax can be improved. The
> RFC tries to go into detail on explaining the rationale for the chosen
> approach. Additionally, it proposes a few alternate syntax options,
> although none of them are very satisfactory.
>
> At this point I'm unsure whether a proposal can satisfy all camps. Let
> me know if you have any thoughts/ideas.
>
> Ilija

As we've discussed elsewhere, I favor option 2: Language level concept.  I 
cannot speak to the implementation details, but let me offer two specific bits 
of justification.

1. The RFC says "For match, whether the block should require returning a value 
depends on whether the match itself returns a value." - I disagree.  Returning 
a value should always be legal; if the value isn't assigned to a variable it is 
lost, but oh well, that's how PHP already works.  Moreover, if the argument is 
rather "if match's result is saved, then each branch *must* return a value", 
well, the same is true for use in many other cases, such as with the null 
short-hands.

2. Speaking of, this is a pattern I find myself writing all the time:

class Foo {
  private array $things;

  public function getThing(string $id): ?Thing {
    $this->things ??= $this->makeThingTable();
    return $this->things[$id] ?? null;
  }

  private function makeThingTable(): array {
    // Something complex here.
  }
}

Allowing multi-line expressions on ??= would allow that to be collapsed to a 
single function, without the need to come up with a name for makeThingTable(), 
or splitting logic between two methods, etc.  I believe that is a valid and 
useful use case for multi-line expressions outside of match() that can/should 
be supported.  (One could argue that it's possible to just use a self-executing 
closure, which is true, but is also verbose and ugly and requires manual 
capture.  That same option is also available for match arms today, with the 
same problem, which is why we're looking for a better solution.)

class Foo {
  private array $things;

  public function getThing(string $id): ?Thing {
    $this->things ??= {
      // Something complex here.
    };
    return $this->things[$id] ?? null;
  }
}


I am flexible on the syntax used.  I agree that a keyword would be more PHP-ish 
than <-, but I wouldn't start a riot either way.  If just { } makes the parsing 
hard, I have in the past suggested {{ }} to denote a multi-line expression, 
which should be sufficiently parser-unique.

> We could settle for a solution that works for all cases, returning null by 
> default. Whether this solution is acceptable is likely a matter of taste. 

That would taste just fine to me, frankly, and I'm OK with the code block shown 
right after it.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to