On Fri, Jun 7, 2024, at 18:03, Benoît Condaminet wrote:
> Hello,
>
> Following the RFC process, I'm sending this to propose a PHP change. More
> precisely a new zend language token.
>
> This is somehow linked to the recently accepted RFC called "new
> MyClass()->method() without parentheses", the goal is to introduce a
> shorthand for the "new" keyword.
>
> *Motivations :*
> The new keyword sometime has a bad DX, for example when chaining Class
> instantiation like this :
> $foobar = new Foo( new Bar(), new Etc());
>
> We can quickly have very long class object construction in some case.
>
> In lot of Framework, to improve DX, static function construct are often used
> to avoid the new keyword, some create additional object builders, etc.
>
> As a first try, I start updated code to completely make the new keyword
> optional, like in Dart language for example, but it require very big change,
> with lot of impact (collision with function).
>
> So here is *my proposal : *
>
> Add a "new" shorthand, using the tilde character : "~"
> I made a POC, and it works well, declaring a new language token T_SHORT_NEW
> that simply reuse ZEND_AST_NEW under the hood.
>
> Here are some example of what it may look like for userland, through some
> tests I wrote :
> --TEST--
> New keyword shorthand
> --FILE--
> <?php
> class A {
> public function b() {
> echo "I'm B";
> }
> }
>
> ~A()->b();
>
> ?>
> --EXPECT--
> I'm B
> Other with nested :
>
> --TEST--
> New keyword shorthand encapsulation
> --FILE--
> <?php
> class Foo {
> public function __construct(
> public string $name
> ) {}
> }
>
> class Bar {
> public function __construct(
> public Foo $foo
> ) {}
> }
>
> $bar = ~Bar(~Foo("I'm foo in bar"));
> echo $bar->foo->name;
>
> ?>
> --EXPECT--
> I'm foo in bar
> As a last word, just wanted to add it will work on nested Attribute too, so
> for example this nested Attribute used in Doctrine :
>
> #[AttributeOverrides([
> new AttributeOverride(
> name: "id",
> column: new Column(name: "guest_id", type: "integer", length: 140)
> ),
> new AttributeOverride(
> name: "name",
> column: new Column(name: "guest_name", nullable: false, unique: true,
> length: 240)
> )]
> )]
>
> Will also work like this :
> #[AttributeOverrides([
> ~AttributeOverride(
> name: "id",
> column: new Column(name: "guest_id", type: "integer", length: 140)
> ),
> ~AttributeOverride(
> name: "name",
> column: new Column(name: "guest_name", nullable: false, unique: true,
> length: 240)
> )]
> )]
>
> About implementation, it should'n have any impact on SAPI or extension, the
> new keyword will still exist, it's just a new shorthand.
>
> I think you get the point, is it something that some of you would be
> interested in? I would be happy to make a proper RFC proposal.
>
> Just registered a wiki account : benconda
>
> Thank you,
>
> --
> Cordialement,
> Benoit Condaminet
Instead of ~ (which reminds me of the pendulum of symbols to written to symbols
and back again every 10ish years; “or” vs “||”), why not make a shorthand way
to write a function that calls a constructor (kinda sorta like C# extension
methods)? Something kinda like:
class MyClass implements Invocable {
public function __construct($i) {}
}
MyClass($i);
Where the Invocable interface defines a function of the same class name in the
namespace that is an alias for a new objects and forwards args to the
constructor. This could be quite handy for value objects.
I’m not necessarily a fan of magic or symbols, but just tossing it out there to
spark ideas.
— Rob