Features related to Object Initializers
| From: | Mike Schinkel | Date: | Mon, 16 Sep 2019 03:13:24 +0000 |
| Subject: | Features related to Object Initializers | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-107133@lists.php.net to get a copy of this message | ||
> On Sep 14, 2019, at 4:47 PM, Rowan Tommins <rowan.collins@gmail.com> wrote:
> I think that's only true because you've actually proposed a number of related but
> different features.
See my other email to the list asking about what is in-bounds and what it out-of-bounds regarding
RFC discussion.
I seemed logical to me to discuss how to improve an RFC, but maybe what you are saying is that we
are only suppose to discuss RFC as it exists today in order to give a black and white, up or down
vote on the entire RFC? That seems counter-productive, but if that is the case and others concur
then so be it.
So to be safe, I have started a new thread for this reply.
> other than initializing additional objects. And if these are additional objects, then named
> parameters work just as well in the nested case as in the non-nested one:
>
> $car = new Car(
> yearOfProduction => 1975,
> vin => "12345678",
> engine => new Engine(
> type => "v8",
> capacity => "270ci",
> ),
> );
Obviously that can be done. However, in practice I often see arrays used instead of objects because
it is so much easier. I doubt that this enhancement will remove the other reasons developers might
continue to use arrays instead:
1. Arrays do not require a developer to name a class, where naming is one of the 2 or 3 hardest
parts of computer science
2. Anonymous classes are more tedious than just creating an array literal so I see most PHP
developers using arrays instead.
3. Defining a class in PHP best practice means creating another file that is physically separate
from the code for said class that must also be (auto-)loaded.
So are you arguing that in all cases where people want structured information they should create a
new class, and if so, what about the three points I just made?
> This already works:
>
> $stats = new class {
> var int $total = 0;
> var int $mean = 0;
> var int $average = 0;
> var int $median = 0;
> };
>
> What doesn't currently work is using variables from lexical scope in the definition:
>
> $stats = new class {
> var int $total = $a + $b;
> var int $mean = $c;
> var int $average = $d;
> var int $median = $e;
> };
In the USA we have a saying:
"Besides that Mrs. Lincoln, how was the play?"
But for those unfamiliar with US history leading up to the revolutionary war, what it means in this
context is:
"Yes your point is correct, but ignores the most relevant concern."
> However, initializer syntax on its own doesn't solve this, because you wouldn't be
> able to specify the types for the properties; just combining existing syntax with initializers would
> give something like this:
>
> $stats = new class {
> var int $total;
> var int $mean;
> var int $average;
> var int $median;
> }{
> total => $a + $a,
> mean => $c,
> average => $d,
> median => $e
> }
You probably missed that I wrote that I was using an alternate initialization syntax that I would
propose instead, which I will illustrate again below. If we allow typing i
$stats = new class {
int $total = $a + $b;
int $mean = $c;
int $average = $d;
int $median = $e;
};
> You could certainly make the syntax of initializers and anonymous class definitions similar,
> but they're not really the same thing.
Noted. To me them being the same or not is not as concerning as the outcome of the features that
may become available in userland.
> The QueryBuilder class in this example has not benefited from object initializers at all;
> passing the Query object rather than separate parameters is a refactoring you can (and probably
> should) do right now.
But many PHP developers are unlikely to do that refactoring initially. They will just fall back to
using arrays, because they are easy, comfortable, less pedantic and less tedious to use.
I would far prefer to have find developers using untyped anonymous objects than arrays because the
former is much easier to refactor to better code than the latter, and this is painfully obvious to
me because of numerous PHP codebases I have been brought in to fix.
Would it be better to introduce a simple-to-use object instantiation syntax so userland PHP
developers would start using it, or would it be better to leave them only one easy option such that
they continue to use arrays?
> As before, the definition of the class itself is simpler, but I think a short-hand syntax for
> constructors would be a better compromise than a syntax that only worked with public properties and
> parameterless constructors.
My problem with short-hand syntax for constructors is they only work in context of constructors.
What about other functions or methods that userland PHP developers currently pass structured arrays
too?
> This is an interesting additional proposal, which I admit would be awkward to implement without
> initializer syntax. One limitation is that it only works if dependencies are declared as concrete
> classes not interfaces
True.
If a function is defined to accept an interface then the caller would be required to pass in an
instance of a class that satisfies the interface.
> which like public properties is not "wrong" per se, but limits the scope of the
> feature.
If we had to have every feature work for everything, we'd never have
foreach, for
example.
My belief is that not every feature needs to apply in all contexts in order to be highly useful. Do
you believe otherwise?
> Named parameters are (or would be) a way of setting a bunch of variables; they're not
> linked as an object of any sort, so I don't think there's a natural comparison to
> anonymous classes at all.
I did not say they _were_ linked, I asked why couldn't/shouldn't they be linked?
They are both a group of named "properties" with associated values. Why are they all not
equivalent to an object?
And why not allow all of them to be treated as an object?
Even if there are represented different internally, I see no reason why they could not be made
equivalent in userland code. Do you?
> If I understand it right, the next example relies on the combination of anonymous class
> initialisers, named class initialisers, and named parameters all using the same syntax,
No, I would say that is not what I am proposing. What I am proposing is that one syntax and one set
of functionality be used to address all three use-cases rather than have three different
functionalities with three different syntaxes, because they seem to be to be all equivalent:
1. anonymous class initialisers,
2. named class initialisers, and
3. named parameters
As Larry Garfield said, we are running out of sigils; making one syntax address multiple use-cases
seems to me like the most responsible thing to do.
> The examples look really neat on their own, but imagine coming on that syntax in someone
> else's code and trying to work out what it was doing.
If I see someFunction({bar => 1, baz => 2}) that tells me that someFunction expects bar and
bar as integers. When calling functions we are not supposed to know how they are implemented, so why
should it matter to the caller whether internally they are captured to individual parameters or into
a single parameter array? And when inside the function, why does it matter how they are passed?
The reason I proposed this is I would really prefer to come on to this syntax in other's code
rather than coming onto the prevailing type of code I see in userland instead; arrays upon arrays.
What is not clear to me is why you see it to be confusing?
> There's definitely some interesting ideas here, but they're not all part of one
> feature,
Can you clarify what you are implying? That I should start other threads to discuss? That I should
create new RFCs?
> and they all rely on particular ways of structuring your code.
Is that problematic? Most language features require code to be structured a particular way.
I am assuming that PHP is not an opinionated language that defines one way to structure code and
shuns all other ways, except for those ways that have been explicitly deprecated by RFC such as
magic quotes. Am I incorrect about this?
-Mike