Hi folks,
What do you think about having a method which returns the class instance
$this
by default only IF its return type is set as self
?
It is very common for fluent class methods to have a verbose return $this;
ending in their body.
But If you have declared self
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
My proposal is to set the instruction return $this;
as optional for
non-static class methods with self
declared as return type.
Example:
class Counter {
public function __construct(private int $counter = 0) {}
public function hit(): self { $this->counter++; }
public function print(): self { echo $this->counter; }
public function split(): self { return new self($this->counter); }
}
$main = (new Counter)->hit()->hit()->hit()->print()
// 3
$sub = $main->split()->hit()->print()
// 4
Thank you for reading my proposal,
please let me know if you like it or if there are any issues with this.
Regards,
Daniele
Le 23 déc. 2022 à 01:08, joke2k joke2k@gmail.com a écrit :
Hi folks,
What do you think about having a method which returns the class instance
$this
by default only IF its return type is set asself
?It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
But If you have declaredself
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
It is still two options, and it is not clear in general which one to pick. You could also say that, if you have object
as return type, there are two options to avoid a return type error: either return the $this
object, or return another object.
My proposal is to set the instruction
return $this;
as optional for
non-static class methods withself
declared as return type.
I’d rather have a syntax saying explicitly that you want to return $this, rather than letting the interpreter guess what you meant. The obvious one is:
public function hit(): $this { $this->counter++; }
Here, there is only one possible return value, and therefore the return
instruction might be reasonably omitted.
The real question is: Is it worth to add special cases for some specific return values?
—Claude
On Fri, Dec 23, 2022 at 10:33 AM Claude Pache claude.pache@gmail.com
wrote:
public function hit(): $this { $this->counter++; }
Here, there is only one possible return value, and therefore the
return
instruction might be reasonably omitted.The real question is: Is it worth to add special cases for some specific
return values?
We do have true, false, and null as return types (
https://www.php.net/releases/8.2/en.php#null_false_true_types). I'm
personally not opposed to having $this
as return type, but it also starts
getting close to short function notations.
Hi Daniele and Claude,
pt., 23 gru 2022 o 10:33 Claude Pache claude.pache@gmail.com napisał(a):
Le 23 déc. 2022 à 01:08, joke2k joke2k@gmail.com a écrit :
Hi folks,
What do you think about having a method which returns the class instance
$this
by default only IF its return type is set asself
?It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
But If you have declaredself
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
It is still two options, and it is not clear in general which one to pick.
You could also say that, if you haveobject
as return type, there are two
options to avoid a return type error: either return the$this
object, or
return another object.My proposal is to set the instruction
return $this;
as optional for
non-static class methods withself
declared as return type.I’d rather have a syntax saying explicitly that you want to return $this,
rather than letting the interpreter guess what you meant. The obvious one
is:public function hit(): $this { $this->counter++; }
Here, there is only one possible return value, and therefore the
return
instruction might be reasonably omitted.
I like the idea of $this
as a return type but also strongly believe that
the use of return $this;
should be forbidden,
eventually for control flow use of return;
might be justified.
Cheers,
Michał Marcin Brzuchalski
Thanks for the feedback!
It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
But If you have declaredself
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
It is still two options, and it is not clear in general which one to pick.
You could also say that, if you haveobject
as return type, there are two
options to avoid a return type error: either return the$this
object, or
return another object.
Yes but declaring self
is more strict than object
.
And talking about the word itself... Declaring to return (your-)self
but
you could return someone-else of the same type as you.
But it is ok, it refers to the class name not the instance. just semantic.
My proposal is to set the instruction return $this;
as optional for
non-static class methods with
self
declared as return type.I’d rather have a syntax saying explicitly that you want to return $this,
rather than letting the interpreter guess what you meant. The obvious one
is:public function hit(): $this { $this->counter++; }
Here, there is only one possible return value, and therefore the
return
instruction might be reasonably omitted.
Return $this
is a valid alternative indeed. It is an explicit subclass of
returning self
which has a default return object, itself.
Le 23 déc. 2022 à 13:46, joke2k joke2k@gmail.com a écrit :
It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
But If you have declaredself
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
It is still two options, and it is not clear in general which one to pick. You could also say that, if you have
object
as return type, there are two options to avoid a return type error: either return the$this
object, or return another object.Yes but declaring
self
is more strict thanobject
.
And talking about the word itself... Declaring to return (your-)self
but you could return someone-else of the same type as you.
But it is ok, it refers to the class name not the instance. just semantic.
It is not about being less or more restricted, it is about being plainly ambiguous.
class Point {
public function __construct(
protected float $x
, protected float $y
) { }
public function withY(float $y): static {
$newPoint = clone $this;
$newPoint->y = $y;
// oops, forgot “return $newPoint;”
}
}
With implicit behaviours (at least when there is more than one option), such sort of bugs become less apparent at runtime. Therefore, implicit behaviour ought to be avoided if possible.
—Claude
Yes but declaring
self
is more strict thanobject
.
And talking about the word itself... Declaring to return (your-)self
but you could return someone-else of the same type as you.
But it is ok, it refers to the class name not the instance. just semantic.It is not about being less or more restricted, it is about being plainly ambiguous.
Another big advantage of "return $this" is that it can't affect any existing code. Granted, a function marked :self or :static which currently fails to return would be a runtime error, but changing that error into an implicit return $this could be very dangerous.
Regards,
--
Rowan Tommins
[IMSoP]
Thanks for the feedback!
It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
But If you have declaredself
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
It is still two options, and it is not clear in general which one to
pick.
You could also say that, if you haveobject
as return type, there are
two
options to avoid a return type error: either return the$this
object,
or
return another object.Yes but declaring
self
is more strict thanobject
.
And talking about the word itself... Declaring to return (your-)self
but
you could return someone-else of the same type as you.
But it is ok, it refers to the class name not the instance. just semantic.
I would rather endure it returns the used instance and not another one with
a compatible interface. Not doing do is actually confusing to me, as per
the meaning of self. .
Or maybe, if the goal is to ease declaration of fluent interfaces (methods
chaining), declaring a class fluent (annotation?) would achieve the same
with ambiguous names?
Hi folks,
What do you think about having a method which returns the class instance
$this
by default only IF its return type is set asself
?It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
But If you have declaredself
as return type into a non-static class
method you have only two options to return:
- the $this object
- another instance of the same class or subclass
... in order to avoid a return type error.
My proposal is to set the instruction
return $this;
as optional for
non-static class methods withself
declared as return type.Example:
class Counter { public function __construct(private int $counter = 0) {} public function hit(): self { $this->counter++; } public function print(): self { echo $this->counter; } public function split(): self { return new self($this->counter); } } $main = (new Counter)->hit()->hit()->hit()->print() // 3 $sub = $main->split()->hit()->print() // 4
Thank you for reading my proposal,
please let me know if you like it or if there are any issues with this.Regards,
Daniele
As someone who used Scala for a number of years, I’d be very much
against this idea. Scala automatically returns the last line of any
function and we found it fairly difficult to maintain once the project
got fairly large and ended up switching to explicit returns. Mostly we
found it too easy to return the wrong thing.
In all fairness, I guess you technically don’t have to use it if you
don’t want to (you can use explicit returns), but IMHO, using this
would greatly affect readability. Every function you read that doesn’t
have a return, you’d have to check if the return type is self/static
and verify it is void.
--
Robert Landers
Software Engineer
Utrecht NL
Hi Daniele
Hi folks,
What do you think about having a method which returns the class instance
$this
by default only IF its return type is set asself
?It is very common for fluent class methods to have a verbose
return $this;
ending in their body.
Instead of adding special syntax to make writing fluent accessors
easier, I wonder if something akin to Dart's cascade operator would be
a better approach.
https://dart.dev/guides/language/language-tour#cascade-notation
$foo
..setBar('bar')
..setBaz('baz');
The syntax is just copied from Dart, there's probably a better fit for
PHP. .. would invoke a method call but discard the return value,
evaluating to the lhs of the method call instead.
With an operator solution one can use fluent method calls on APIs that
aren't specifically designed for it when desired, accessors can become
leaner as return $this is no longer necessary, and it becomes obvious
at call-site that the chained methods are called on the same object.
I'm not sure about syntax or the fact that Dart allows property
assignments in combination with .. as that makes the syntax ambiguous
(or whitespace sensitive), but that wouldn't be necessary for what
you're proposing.
Example of the ambiguity:
$foo
..bar = $bar
..baz()
// Could be parsed as
$foo..(bar = $bar)..baz()
$foo..bar = ($bar..baz())
An alternative might be a C# style syntax which would make property
assignments unambiguous.
$foo {
setBar('bar'),
baz = 'baz',
}
But this is also longer and less readable (to me at least).
Anyway, just my unrefined thoughts. I would not support implicit
return $this
for self or static. At the very least, the return type
should be $this (which is essentially a sub-type of static) but that
too doesn't seem like an elegant solution to me.
Ilija