On Wed, Mar 25, 2020, at 5:57 AM, Nicolas Grekas wrote:
> > > https://hive.blog/php/@crell/improving-php-s-object-ergonomics

> > Named parameters are a pretty tough topic. I think one of the main points
> > of contention is that they make the parameters names part of the API
> > contract, and as such also subject to LSP. Your proposal offers two
> > possible ways to side-step this: First, by making named parameters opt-in
> > with a special syntax {}. Second, by limiting them to constructors. The
> > latter variant still exposes parameter names in the API, but at least does
> > not require their preservation across inheritance, as constructors are
> > excluded from LSP. I'm somewhat torn on this, because it makes named
> > parameters unusable with the very large body of existing methods, and
> > introduces an inconsistency in which methods can use named params and which
> > don't.
> >
> 
> I'd like to propose something on the topic.
> I'm adding object literals to the mix because that's another feature of the
> language that we're missing a lot IMHO.
> Actually, there is one existing syntax for objects: (object) [...]
> 
> My proposal is to allow any class in the casting operator: (Foo) [...]
> By default, all keys of the casted array would map to properties (with an
> error when no matching property exists in the current visibility scope). We
> would then allow for a new constructor method, either:
> public function __create(array $values)
> or:
> public static function __create(array $values): static
> 
> This method would take over the cast operator and decide how to construct
> an instance of such a class.
> 
> There is one drawback: accepted keys are not documented. Sure, property
> declarations can give a big hint.
> 
> But I think we can solve this issue later: it's not a blocker to still make
> things work nicely. Also, this issue already exists with all methods that
> accept an array of options - and we'll find a solution for those - either
> using docblocks (there are already ways to use them for that) or using
> attributes (would be the best of course, once we have them.)
> 
> Note that this __create() method looks a lot like __unserialize(): it's
> just called at a different place, but the implementations could be
> essentially the same.

Interesting.  If that allowed populating private properties than that would be 
more capable than either of the initializer proposals that have been put 
forward.

However, this alternate deserialization (as you note, it's basically 
__unserialize by another name) brings up other issues:

1) If it's a large number of properties, the __create method would still need 
to manually assign them to properties, just like constructors now.  It wouldn't 
benefit from constructor promotion.

2) What's its order of execution with the constructor?  Vis, does the 
constructor run after __create or before?  Does __construct get any parameters 
passed to it?  If it doesn't get called, that's yet another way to bypass the 
constructor and therefore bypass object validation.  ("Make invalid states 
unrepresentable".  If the properties don't logically make sense with each other 
that should be rejected as early as possible; syntactically if we can, via 
early validation if not.)

Named parameters have neither of those issues, as data still only comes in via 
the constructor so both promotion and validation work fine.

> Regarding the remainder, I think that all of readonly properties,
> > asymmetric visibility and property accessors have their place and value,
> > with some overlap between them. As you already mentioned, the previous
> > property accessors proposal also included asymettric visibility as a
> > special case, and that's how I would introduce it as well.
> >
> 
> Máté suggested this syntax and it has my preference over the one you menton
> Larry: doubling the visibility keyword could be enough to express
> read+write access:
> 
> public private $property; <= public read access, private write access

In that syntax, you have to remember which one comes first.  There's no 
indication for the casual reader why 

public private $property;

and 

private public $property;

are different.  Plus, just looking at it, "wait, it's public and private?  WTF? 
 That doesn't even make sense."

It also doesn't extend gracefully to property accessors.  Whatever accessors 
do, if they ever get resolved, would conflict with that, and thus we'd have 
that many more weird combinations of property metadata that are incompatible.

The whole point of the syntax I proposed for asymmetric visibility is that it's 
gracefully extensible, even if a little more verbose.  (If we can find a syntax 
that is less verbose while still gracefully extensible, I am on board with 
that.)

--Larry Garfield

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

Reply via email to