Re: [PHP-DEV] [RFC][Draft] Match block

2023-09-13 Thread Levi Morrison
> 2. Support block expressions as a language-level concept, analogous to
> https://doc.rust-lang.org/reference/expressions/block-expr.html

This is my personal preference. As I mentioned in chat, if we go this
route, there is a notable pain point: in "short" closures which have
blocks, how do you capture by reference if needed?

Consider this situation:

// function array_push(array &$array, mixed ...$values): int;
$array = [];
$value = fn ($x) => array_push($array, $x);

I have an incomplete idea about allowing `&` at the call-site if and
only if the corresponding parameter is taken by reference:

// Ok, $array is taken by reference in array_push
$value = fn ($x) => array_push(&$array, $x);

// Not ok, ...$values are not taken by reference in array_push
$key = '';
$value = fn ($x) => array_push(&$array, &$key, $x);

Then, when `&` is given at the call-site, that variable is captured by
reference. If they don't want it to be captured by-reference, then
they have choices:

// Choice 1: omit the `&` at the call-site.
$value = fn ($x) => array_push($array, $x);

// Choice 2: copy the array.
// Assumes blocks are allowed.
$value = fn ($x) => {
$copied = $array;
array_push(&$copied, $x);
}

It would still be valid to omit `&` at the call-site in PHP 8.x so a
transition can be made. Theoretically, we could make it required in
PHP 9.0 or 10.0.

Nikita started an RFC for this 5 years ago:
https://externals.io/message/101254

I do not know exactly why it was not voted on. There was substantial
drama in the discussion that was, in my opinion at least, not really
relevant to the RFC contents.

The original motivations still stand:
 1. The code becomes more readable by humans.
 2. The code becomes more readable by analyzers and optimizers.

And now we have another reason:
 3. Enables auto-capture by-reference when it is necessary.

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



Re: [PHP-DEV] [RFC][Draft] Match block

2023-09-12 Thread Larry Garfield
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



Re: [PHP-DEV] [RFC][Draft] Match block

2023-09-10 Thread Deleu
On Sun, Sep 10, 2023 at 12:51 PM Rowan Tommins 
wrote:

> On 10 September 2023 15:35:44 BST, Deleu  wrote:
> > ... until we manage to gather enough
> >voters to overcome the "no-auto-capture" camp.
>
>
> I think that's a rather adversarial / political way to put it. I believe
> the aim of voting should be to measure consensus, not replace it.
>

Communities are a live organism and I reckon the current pool of voters are
not exactly the same as the ones voting 15 years ago. Even if someone used
to be an active voter 15 years ago and is still present to this day, maybe
their mindset or the language itself has changed enough to yield a
different result. What I meant to say with "enough voters to overcome the
no-auto-capture camp" is that the current camp that blocks this line of
reasoning can either change their mind, disengage from the project
(reducing no-votes) or simply be outvoted by a new wave of contributors.


> A more productive wording would be "until we can find a version of the
> feature that satisfies the concerns raised in previous discussions".
>

I think this is wishful thinking as the previous discussions has already
shown that the disagreement is fundamental. What I want is ===
auto-capture. I don't want something that resembles auto-capture or
facilitates capturing. Previous discussion has already established that one
camp of voters don't want auto-capture. They might be open to a compromise
on facilitating auto-capture, which is where there's no expectation of a
version which satisfies the concerns.


I think there are some really powerful things that could be done with new
> types of block, and new ways of scoping variables, but have concerns about
> how to fit them with the existing language. I will continue to engage in
> good faith in discussing those proposals, but find it disheartening to be
> labelled as part of a "camp" that needs to be "overcome".


I meant no disrespect and I apologize for any negative effect that my
wording may have caused. I do have difficulty expressing it differently.
There's this core concept which I see as a great improvement to the
development of PHP code and there's philosophical disagreement on whether
it's a good thing or not. Perhaps there is really no *need* to overcome
that camp of voters and maybe they are what's protecting the language from
walking towards a bad path. We just have no way of settling this. In such
fundamental disagreement, someone is bound to be unsatisfied with the
outcome. Either we will manage to get auto-capture and see if it leads to a
bad outcome or we won't have it. Either not having it is protecting the
language or not having it is preventing a great step forward. There's no
experiment, feature-flag or time-machine options.

... I can't help but see the irony that auto-capturing would create
something "alien" to the PHP language and since we don't have that, there's
a new proposal to create a different "alien" concept which is a
kind-of-return within a block statement that doesn't exactly mean "return"
(the <- token / resolve keyword).

-- 
Marco Deleu


Re: [PHP-DEV] [RFC][Draft] Match block

2023-09-10 Thread Rowan Tommins
On 10 September 2023 15:35:44 BST, Deleu  wrote:
> ... until we manage to gather enough
>voters to overcome the "no-auto-capture" camp.


I think that's a rather adversarial / political way to put it. I believe the 
aim of voting should be to measure consensus, not replace it.

A more productive wording would be "until we can find a version of the feature 
that satisfies the concerns raised in previous discussions".

I think there are some really powerful things that could be done with new types 
of block, and new ways of scoping variables, but have concerns about how to fit 
them with the existing language. I will continue to engage in good faith in 
discussing those proposals, but find it disheartening to be labelled as part of 
a "camp" that needs to be "overcome".

Regards,

-- 
Rowan Tommins
[IMSoP]

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



Re: [PHP-DEV] [RFC][Draft] Match block

2023-09-10 Thread Deleu
On Fri, Sep 8, 2023 at 7: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
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>
Hi Ilija,

This seems like an interesting subject for the PHP language, but
unfortunately doesn't take the direction I would much have preferred. The
use of `<-` to denote a different style of return statement in a block
feels quite "alien" (for lack of a better word) in the language for me. In
addition to that, I'm also not sure if there's anything else in PHP that
behaves differently when a return value is expected or not - this is in
relation to the difference between `$result = match()` vs `match()` without
expecting a result. If there's anything else in PHP that already has a
similar behavior, it might be worth adding it to the RFC so that we can
relate the subjects.

To me it would be much better to stick with the existing language
constructs just as-is.

```
 {
echo "foo branch reached\n";
},
});
// foo branch reached
// NULL

var_dump(match ('foo') {
'foo' => {
echo "foo branch reached\n";

return 'this will be dumped';
},
});
// foo branch reached
// string(19) "this will be dumped

var_dump(fn () => {
echo "auto-capturing short closure invoked\n";
}());
// auto-capturing short closure invoked
// NULL

var_dump(fn () => {
return 'foo';
}());
// string(3) "foo"

$foo ??= {
bar();
};
var_dump($foo);
// NULL

$foo ??= {
bar();

return 'baz';
};
var_dump($foo);
// string(3) "baz"
```

There's a somewhat related discussion on this RFC
https://wiki.php.net/rfc/auto-capture-closure#multi-line_expressions which
comes to mind and was just 2 votes short of have been approved.
Other good-related RFCs are https://wiki.php.net/rfc/short-match and
https://wiki.php.net/rfc/short-functions which creates a really nice
symmetry in the language syntax.

Ultimately, this is a sad 10-year-long discussion (as summarised here:
https://externals.io/message/113740#113833) that seems impossible to move
forward within the PHP language. The door of creating of a block with
auto-capture look-and-feel much better across many different aspects of the
language, but it's always shutdown by enough long-time voters.

Overall, between the choice of creating a new syntax that "kind of
represents return statements on specific scenarios" or option 3 - do
nothing, I would prefer to do nothing until we manage to gather enough
voters to overcome the "no-auto-capture" camp.

-- 
Marco Deleu


Re: [PHP-DEV] [RFC][Draft] Match block

2023-09-10 Thread Rowan Tommins
On 8 September 2023 23:16:07 BST, Ilija Tovilo  wrote:
>Hello everyone
>
>I've been working on match blocks over the last few weeks.
>https://wiki.php.net/rfc/match_blocks


Hi Ilija,

Thanks for working on this. A few initial thoughts...


The use of "<-" as the new token doesn't fit the language very well. The 
"family" it belongs to are all keywords not symbols: return, yield, throw, 
break, continue. I understand that you don't want to reuse one of those, but 
presume a new keyword would not need to be fully reserved?

Relatedly, I note that in the RFC text, you've talked about the arms 
"returning" a value, but also made clear that a return statement is also 
allowed. I think it would be clearer to pick a term other than "return" for 
what this token does, and use it consistently.

My suggestion to start the ball rolling is "resolve" - that is, "The block 
resolves to a value given after the 'resolve' keyword."


Having said all that, the ability to put control flow like return and yield 
into match statements feels a little weird to me. Again, it's partly the syntax 
- the "=>" is reminiscent of array literals and short lambdas, which are very 
much expressions not statements.

You say in the introduction that part of the motivation is to more completely 
replace "switch", but I wonder if that would be better solved with a different 
construct that handles the non-expression-like uses of switch. In particular, 
although fall-through by default (if "break" is not specified) is definitely a 
historic mistake, the *ability* to fall through to another case is sometimes 
useful, so those cases would still not be convertible to "match".

A "strict switch" could look more like the current control flow structures, but 
add strict equality (and pattern matching in future) and remove implicit 
fall-through, without having to squeeze into the same syntax as match 
expressions.


My final thought for now is a short and slightly off-topic one: someone really 
needs to look into adding opt-in block scoping to PHP, similar to JS "let". It 
would fit so well with proposals like this one!


Regards,

-- 
Rowan Tommins
[IMSoP]

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



[PHP-DEV] [RFC][Draft] Match block

2023-09-08 Thread Ilija Tovilo
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

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