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
Hi Benoît,
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.
I would point out that ~ is an existing operator, bitwise not. Is there not the same ambiguity with that as with not having the new keyword at all? Because PHP has classes and functions in different namespaces ~SomeClass() looks exactly the same as ~SomeFunction(), and ~$someVar() would be just as ambiguous.
I would prefer to see the new keyword go away as well, but as long as functions and classes are in separate namespaces, that might be difficult.
-John
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
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 CondaminetInstead 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
--
I'm not a fan of using ~ for this shorthand, due to the same issues that
have been brought up elsewhere (i.e. it already has meaning). But the
idea of a new interface auto-defining a function of the same name is
attractive. It's something I've done manually to mirror code in PHP from
other implementations existing in Scala leveraging case classes.
https://docs.scala-lang.org/tour/case-classes.html for anyone unfamiliar
with the construct:
case class Book(isbn: String)
val frankenstein = Book("978-0486282114")
Doing something like this in PHP is a bit more ... verbose today:
class Book
{
public function __construct(public string $isbn) {}
}
function Book(string $isbn): Book
{
return new Book($isbn);
}
$frankenstein = Book("978-0486282114")
That's a lot of boilerplate for the shorthand to not require a new
keyword. Which is to say, I both agree in principle with the RFC and
think this would add value (particularly if I could extend the default
behavior of this kind of interface to support immutability, comparison,
etc similar to Scala case classes). I'm just not a fan of the current ~
proposal.
~Eric
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
--I'm not a fan of using ~ for this shorthand, due to the same issues
that have been brought up elsewhere (i.e. it already has meaning). But
the idea of a new interface auto-defining a function of the same name
is attractive. It's something I've done manually to mirror code in PHP
from other implementations existing in Scala leveraging case classes.https://docs.scala-lang.org/tour/case-classes.html for anyone
unfamiliar with the construct:case class Book(isbn: String) val frankenstein = Book("978-0486282114")
Doing something like this in PHP is a bit more ... verbose today:
class Book { public function __construct(public string $isbn) {} } function Book(string $isbn): Book { return new Book($isbn); } $frankenstein = Book("978-0486282114")
That's a lot of boilerplate for the shorthand to not require a
new
keyword. Which is to say, I both agree in principle with the RFC and
think this would add value (particularly if I could extend the default
behavior of this kind of interface to support immutability, comparison,
etc similar to Scala case classes). I'm just not a fan of the current ~
proposal.~Eric
The issue with auto-generating a function constructor for a class is that we still don't have function autoloading. Which means this:
// Point.php
#[MakeFactoryFunction] (or whatever)
class Point {
public function __construct(public int $x, public int $y) {}
}
// index.php
$p = Point(4, 5);
will look for a function named "Point", not find one defined yet, and fatal.
If we had function autoloading, that would work, assuming a reasonable generic autoloader for that case could be written. Who was it that's been talking about that for a while? :-)
Or if we had some marker to indicate "this function call is a wrapper for a class so autoload it like a class", that could then trigger the class autoloader. But... that's basically what the original ~ proposal is, in the end. Though I agree that ~ is not a great symbol for it. PHP has, sadly, run out of unused symbols. (I've run into this a couple of times now.)
--Larry Garfield
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
--I'm not a fan of using ~ for this shorthand, due to the same issues
that have been brought up elsewhere (i.e. it already has meaning). But
the idea of a new interface auto-defining a function of the same name
is attractive. It's something I've done manually to mirror code in PHP
from other implementations existing in Scala leveraging case classes.https://docs.scala-lang.org/tour/case-classes.html for anyone
unfamiliar with the construct:case class Book(isbn: String) val frankenstein = Book("978-0486282114")
Doing something like this in PHP is a bit more ... verbose today:
class Book { public function __construct(public string $isbn) {} } function Book(string $isbn): Book { return new Book($isbn); } $frankenstein = Book("978-0486282114")
That's a lot of boilerplate for the shorthand to not require a
new
keyword. Which is to say, I both agree in principle with the RFC and
think this would add value (particularly if I could extend the default
behavior of this kind of interface to support immutability, comparison,
etc similar to Scala case classes). I'm just not a fan of the current ~
proposal.~Eric
The issue with auto-generating a function constructor for a class is that we still don't have function autoloading. Which means this:
// Point.php
#[MakeFactoryFunction] (or whatever)
class Point {
public function __construct(public int $x, public int $y) {}
}// index.php
$p = Point(4, 5);
will look for a function named "Point", not find one defined yet, and fatal.
If we had function autoloading, that would work, assuming a reasonable generic autoloader for that case could be written. Who was it that's been talking about that for a while? :-)
Or if we had some marker to indicate "this function call is a wrapper for a class so autoload it like a class", that could then trigger the class autoloader. But... that's basically what the original ~ proposal is, in the end. Though I agree that ~ is not a great symbol for it. PHP has, sadly, run out of unused symbols. (I've run into this a couple of times now.)
--Larry Garfield
Hello Benoit.
others already pointed out problems with the $obj = ~C();
syntax,
but also with the other option, $obj = C();
.
Personally I would prefer a suffix operator that would look similar to
a static method call.
This would make it a lot easier to switch between calling a static
factory and "new."
Unfortunately, $obj = C::new();
is not an option, because "new" is a
legal method name, so there could already be existing methods with
that name.
Also, $obj = C::__construct();
would be just wrong.
But if we can find anything in that direction, I would much prefer it
over a prefix operator.
E.g. $obj = C::+();
is currently not valid syntax, so it would be a
candidate, even though I don't really like it.
-- Andreas
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
--I'm not a fan of using ~ for this shorthand, due to the same issues
that have been brought up elsewhere (i.e. it already has meaning). But
the idea of a new interface auto-defining a function of the same name
is attractive. It's something I've done manually to mirror code in PHP
from other implementations existing in Scala leveraging case classes.https://docs.scala-lang.org/tour/case-classes.html for anyone
unfamiliar with the construct:case class Book(isbn: String) val frankenstein = Book("978-0486282114")
Doing something like this in PHP is a bit more ... verbose today:
class Book { public function __construct(public string $isbn) {} } function Book(string $isbn): Book { return new Book($isbn); } $frankenstein = Book("978-0486282114")
That's a lot of boilerplate for the shorthand to not require a
new
keyword. Which is to say, I both agree in principle with the RFC and
think this would add value (particularly if I could extend the default
behavior of this kind of interface to support immutability, comparison,
etc similar to Scala case classes). I'm just not a fan of the current ~
proposal.~Eric
The issue with auto-generating a function constructor for a class is that we still don't have function autoloading. Which means this:
// Point.php
#[MakeFactoryFunction] (or whatever)
class Point {
public function __construct(public int $x, public int $y) {}
}// index.php
$p = Point(4, 5);
will look for a function named "Point", not find one defined yet, and fatal.
If we had function autoloading, that would work, assuming a reasonable generic autoloader for that case could be written. Who was it that's been talking about that for a while? :-)
Or if we had some marker to indicate "this function call is a wrapper for a class so autoload it like a class", that could then trigger the class autoloader. But... that's basically what the original ~ proposal is, in the end. Though I agree that ~ is not a great symbol for it. PHP has, sadly, run out of unused symbols. (I've run into this a couple of times now.)
--Larry Garfield
Hello Benoit.
others already pointed out problems with the$obj = ~C();
syntax,
but also with the other option,$obj = C();
.Personally I would prefer a suffix operator that would look similar to
a static method call.
This would make it a lot easier to switch between calling a static
factory and "new."Unfortunately,
$obj = C::new();
is not an option, because "new" is a
legal method name, so there could already be existing methods with
that name.
Also,$obj = C::__construct();
would be just wrong.But if we can find anything in that direction, I would much prefer it
over a prefix operator.
E.g.$obj = C::+();
is currently not valid syntax, so it would be a
candidate, even though I don't really like it.-- Andreas
If we wanted a suffix, why not just use an empty ::?
$frankenstein = Book::($isbn);
— Rob
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
--I'm not a fan of using ~ for this shorthand, due to the same issues
that have been brought up elsewhere (i.e. it already has meaning). But
the idea of a new interface auto-defining a function of the same name
is attractive. It's something I've done manually to mirror code in PHP
from other implementations existing in Scala leveraging case classes.https://docs.scala-lang.org/tour/case-classes.html for anyone
unfamiliar with the construct:case class Book(isbn: String) val frankenstein = Book("978-0486282114")
Doing something like this in PHP is a bit more ... verbose today:
class Book { public function __construct(public string $isbn) {} } function Book(string $isbn): Book { return new Book($isbn); } $frankenstein = Book("978-0486282114")
That's a lot of boilerplate for the shorthand to not require a
new
keyword. Which is to say, I both agree in principle with the RFC and
think this would add value (particularly if I could extend the default
behavior of this kind of interface to support immutability, comparison,
etc similar to Scala case classes). I'm just not a fan of the current ~
proposal.~Eric
The issue with auto-generating a function constructor for a class is that we still don't have function autoloading. Which means this:
// Point.php
#[MakeFactoryFunction] (or whatever)
class Point {
public function __construct(public int $x, public int $y) {}
}// index.php
$p = Point(4, 5);
will look for a function named "Point", not find one defined yet, and fatal.
If we had function autoloading, that would work, assuming a reasonable generic autoloader for that case could be written. Who was it that's been talking about that for a while? :-)
Or if we had some marker to indicate "this function call is a wrapper for a class so autoload it like a class", that could then trigger the class autoloader. But... that's basically what the original ~ proposal is, in the end. Though I agree that ~ is not a great symbol for it. PHP has, sadly, run out of unused symbols. (I've run into this a couple of times now.)
--Larry Garfield
Hello Benoit.
others already pointed out problems with the$obj = ~C();
syntax,
but also with the other option,$obj = C();
.Personally I would prefer a suffix operator that would look similar to
a static method call.
This would make it a lot easier to switch between calling a static
factory and "new."Unfortunately,
$obj = C::new();
is not an option, because "new" is a
legal method name, so there could already be existing methods with
that name.
Also,$obj = C::__construct();
would be just wrong.But if we can find anything in that direction, I would much prefer it
over a prefix operator.
E.g.$obj = C::+();
is currently not valid syntax, so it would be a
candidate, even though I don't really like it.-- Andreas
If we wanted a suffix, why not just use an empty ::?
$frankenstein = Book::($isbn);
— Rob
I am not strictly opposed to $obj = C::()
.
One problem I can imagine is $obj = C::{$method}();
, where for some
reason null or empty string '' is passed as $method. Currently, php
will fail if this happens. But with the C::() syntax, it would then
silently create a new instance.
The same would happen if an unlucky find/replace removes the method name.
Not sure if that's a blocker.
-- Andreas
Le ven. 7 juin 2024, 21:31, Larry Garfield larry@garfieldtech.com a
écrit :
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
--I'm not a fan of using ~ for this shorthand, due to the same issues
that have been brought up elsewhere (i.e. it already has meaning). But
the idea of a new interface auto-defining a function of the same name
is attractive. It's something I've done manually to mirror code in PHP
from other implementations existing in Scala leveraging case classes.https://docs.scala-lang.org/tour/case-classes.html for anyone
unfamiliar with the construct:case class Book(isbn: String) val frankenstein = Book("978-0486282114")
Doing something like this in PHP is a bit more ... verbose today:
class Book { public function __construct(public string $isbn) {} } function Book(string $isbn): Book { return new Book($isbn); } $frankenstein = Book("978-0486282114")
That's a lot of boilerplate for the shorthand to not require a
new
keyword. Which is to say, I both agree in principle with the RFC and
think this would add value (particularly if I could extend the default
behavior of this kind of interface to support immutability, comparison,
etc similar to Scala case classes). I'm just not a fan of the current ~
proposal.~Eric
The issue with auto-generating a function constructor for a class is that
we still don't have function autoloading. Which means this:// Point.php
#[MakeFactoryFunction] (or whatever)
class Point {
public function __construct(public int $x, public int $y) {}
}// index.php
$p = Point(4, 5);
will look for a function named "Point", not find one defined yet, and
fatal.If we had function autoloading, that would work, assuming a reasonable
generic autoloader for that case could be written. Who was it that's been
talking about that for a while? :-)Or if we had some marker to indicate "this function call is a wrapper for
a class so autoload it like a class", that could then trigger the class
autoloader. But... that's basically what the original ~ proposal is, in
the end. Though I agree that ~ is not a great symbol for it. PHP has,
sadly, run out of unused symbols. (I've run into this a couple of times
now.)--Larry Garfield
Thank you all for these answer, I miss the not bitwise operator... Sorry
about that.
Totally agree, look like we run out of unused symbol. And that it's maybe
not the ideal solution to add a new one or combination of existing.
Benoit.
Le 07/06/2024 à 18:03, Benoît Condaminet a écrit :
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.
Hello,
I sincerely do not want to see a new operator for replacing the "new"
operator, because then we would have two different syntaxes which would
be semantically equivalent.
Creating a new object, in most API design, is not something you do very
often, especially when working in a framework that does it for you
(dependency injection, etc...).
And, moreover, when I'm searching who what where was created an specific
class instance, I regex grep for "new\s+ClassName" and in most case, it
works like a charm. If you add an operator for this, it simply will
create a huge cognitive dissonance for simply no added value at all.
"New" is working fine, adding a shortcut for the sake of adding a
shortcut to something you don't write that much doesn't worth it in my
opinion: there are much more disadvantages that benefits.
Best regards,
Pierre
I sincerely do not want to see a new operator for replacing the "new"
operator, because then we would have two different syntaxes which would
be semantically equivalent.Creating a new object, in most API design, is not something you do very
often, especially when working in a framework that does it for you
(dependency injection, etc...).
This is not entirely true. Creating a new service object, yes, you rarely never do that yourself. Creating a new data object (value object, struct object, DTO, and a dozen other terms) is something that should happen more than most PHP developers currently do, because most of us have primitive obsession. (Or array obsession.)
Consider attributes: Any time you want to have an object as the value for one of the arguments to an attribute, you need a "new." Any time you create a value object for a more strongly typed parameter than the horrid $options array, you'll be using "new."
So I'm sympathetic to making that syntax easier, and would be OK with it if a workable syntax was found. But so far in this thread, a workable syntax has not been found.
I agree it's not the greatest usability concern in PHP right now, though.
--Larry Garfield
Le 07/06/2024 à 21:38, Larry Garfield a écrit :
I sincerely do not want to see a new operator for replacing the "new"
operator, because then we would have two different syntaxes which would
be semantically equivalent.Creating a new object, in most API design, is not something you do very
often, especially when working in a framework that does it for you
(dependency injection, etc...).
This is not entirely true. Creating a new service object, yes, you rarely never do that yourself. Creating a new data object (value object, struct object, DTO, and a dozen other terms) is something that should happen more than most PHP developers currently do, because most of us have primitive obsession. (Or array obsession.)Consider attributes: Any time you want to have an object as the value for one of the arguments to an attribute, you need a "new." Any time you create a value object for a more strongly typed parameter than the horrid $options array, you'll be using "new."
So I'm sympathetic to making that syntax easier, and would be OK with it if a workable syntax was found. But so far in this thread, a workable syntax has not been found.
I agree it's not the greatest usability concern in PHP right now, though.
--Larry Garfield
I understand your point, but why replacing "new" which is basically an
operator, with another operator ?
I do agree with you that when you use value objects, you need it a lot,
but I'd much prefer having a JS like value objects initializer syntax,
such as Point {x: 1, y: 2}
syntax than creating another way to call
the constructor, which already has a mastered and comprehensive syntax
which is simply new
.
As you said, it's not the greatest usability concern in PHP right now.
Pierre
Hi all.
Em sex., 7 de jun. de 2024 às 17:53, Pierre pierre-php@processus.org
escreveu:
I do agree with you that when you use value objects, you need it a lot,
but I'd much prefer having a JS like value objects initializer syntax,
such asPoint {x: 1, y: 2}
syntax than creating another way to call
the constructor, which already has a mastered and comprehensive syntax
which is simplynew
.
I also think that new
(4 chars, if we count the blank space) is short
enough.
But a JS-like syntax that's already known for representing objects could be
used.
I'm sympathetic to something like this (changing the OP examples):
class A {
public function b() {
echo "I'm B";
}
}
A::{}->b();
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;
#[AttributeOverrides([
AttributeOverride::{
name: "id",
column: Column::{ name: "guest_id", type: "integer", length: 140 }
},
AttributeOverride::{
name: "name",
column: Column::{ name: "guest_name", nullable: false, unique:
true, length: 240 }
}]
)]
#[AttributeOverrides([
AttributeOverride::{
name: "id",
column: Column::{ name: "guest_id", type: "integer", length: 140 }
},
AttributeOverride::{
name: "name",
column: Column::{ name: "guest_name", nullable: false, unique:
true, length: 240 }
}]
)]
--
Erick
Hi all.
Em sex., 7 de jun. de 2024 às 17:53, Pierre pierre-php@processus.org escreveu:
I do agree with you that when you use value objects, you need it a lot,
but I'd much prefer having a JS like value objects initializer syntax,
such asPoint {x: 1, y: 2}
syntax than creating another way to call
the constructor, which already has a mastered and comprehensive syntax
which is simplynew
.I also think that
new
(4 chars, if we count the blank space) is short
enough.
But a JS-like syntax that's already known for representing objects
could be used.
I'm sympathetic to something like this (changing the OP examples):class A {
public function b() {
echo "I'm B";
}
}A::{}->b();
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;#[AttributeOverrides([
AttributeOverride::{
name: "id",
column: Column::{ name: "guest_id", type: "integer", length:
140 }
},
AttributeOverride::{
name: "name",
column: Column::{ name: "guest_name", nullable: false, unique:
true, length: 240 }
}]
)]#[AttributeOverrides([
AttributeOverride::{
name: "id",
column: Column::{ name: "guest_id", type: "integer", length:
140 }
},
AttributeOverride::{
name: "name",
column: Column::{ name: "guest_name", nullable: false, unique:
true, length: 240 }
}]
)]--
Erick
We already have named arguments, which gives nearly the same syntax. Writing directly to properties like that makes no sense in a language that has class-private properties and internal constructors. It's fine in Rust or Go that don't have internal constructors, but it's just not a good fit in a PHP-like language.
And new Foo(a: 'A", b: 'B") is already perfectly readable and self-documenting. Yet another constructor-invoke syntax on top of that would offer nothing.
--Larry Garfield
On Fri, Jun 7, 2024 at 11:50 PM Larry Garfield larry@garfieldtech.com
wrote:
Hi all.
Em sex., 7 de jun. de 2024 às 17:53, Pierre pierre-php@processus.org
escreveu:
I do agree with you that when you use value objects, you need it a lot,
but I'd much prefer having a JS like value objects initializer syntax,
such asPoint {x: 1, y: 2}
syntax than creating another way to call
the constructor, which already has a mastered and comprehensive syntax
which is simplynew
.I also think that
new
(4 chars, if we count the blank space) is short
enough.
But a JS-like syntax that's already known for representing objects
could be used.
I'm sympathetic to something like this (changing the OP examples):class A {
public function b() {
echo "I'm B";
}
}A::{}->b();
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;#[AttributeOverrides([
AttributeOverride::{
name: "id",
column: Column::{ name: "guest_id", type: "integer", length:
140 }
},
AttributeOverride::{
name: "name",
column: Column::{ name: "guest_name", nullable: false, unique:
true, length: 240 }
}]
)]#[AttributeOverrides([
AttributeOverride::{
name: "id",
column: Column::{ name: "guest_id", type: "integer", length:
140 }
},
AttributeOverride::{
name: "name",
column: Column::{ name: "guest_name", nullable: false, unique:
true, length: 240 }
}]
)]--
ErickWe already have named arguments, which gives nearly the same syntax.
Writing directly to properties like that makes no sense in a language that
has class-private properties and internal constructors. It's fine in Rust
or Go that don't have internal constructors, but it's just not a good fit
in a PHP-like language.And new Foo(a: 'A", b: 'B") is already perfectly readable and
self-documenting. Yet another constructor-invoke syntax on top of that
would offer nothing.--Larry Garfield
Currently there are 3 ways that I mostly see to create objects:
-
new Reponse(...)
, through a public__construct
-
Response::create(...)
, some static constructor that can be named
anything -
response(...)
, where it's basically just a function making the object
I personally don't really use functions for this, it's not for me. I do
however often create static constructors and this means that I basically
have 2 ways of creating objects. Sometimes I wish Response::new()
would
call the __construct
variant, just so I could have all my constructors
use the same syntax. I could make the default constructor private and force
a second static function, but that feels like a lot of extra useless work.
I also think that
new
(4 chars, if we count the blank space) is
short enough.
Strongly agree. This solves a problem nobody has. Feel free to carry on
regardless, though; curious to see where this ends up going.
Bilge
So here is my proposal :
Add a "new" shorthand, using the tilde character : "~"
-10.
Please, don't make PHP as unreadable as Perl. IMO It's two extra characters at worst and would be solved much more elegantly by removing the new keyword entirely.
J
Please, don't make PHP as unreadable as Perl. IMO It's two extra
characters at worst and would be solved much more elegantly by removing the
new keyword entirely.
The new keyword is meaningful and everyone knows what's being done just by
looking at it. Removing it would make the language less readable. But it's
a BC so big that I don't think it can be done anyway.
--
Erick
The new keyword is meaningful and everyone knows what's being done just by looking at it. Removing it would make the language less readable. But it's a BC so big that I don't think it can be done anyway.
FWIW Languages like Dart are very readable without the extra new keyword (it supports instance creation with new or without it). I haven't put any thought into the engine changes that would be necessary to implement a similar syntax where new becomes optional, but I wouldn't be opposed to such a change if there was a PR out there for it.
But I'm with you -- I think new is fine. I 100% don't want to see it replaced with some sort of confusing shorthand, but I might be able to be convinced to make the keyword optional.
I also think in terms of value, cycles would be better spent on other things than to new or not to new .
J