Merging some replies together here...

On Sun, Mar 22, 2020, at 8:36 PM, Levi Morrison via internals wrote:
> > In short: I believe our biggest potential win is to focus on 3 RFCs:
> >
> > * Constructor Promotion
> I would vote yes on this, assuming the implementation is sane.

On Mon, Mar 23, 2020, at 12:55 AM, Michał Brzuchalski wrote:

> That still doesn't resolve issue with lot of boilerplate when you deal with
> small objects for which public readonly is enough like object-initializer
> could. So I'm not sure about my vote here. It does solve only one narrow
> situation for me.

The value here is combining constructor promotion with named parameters.  
Constructor promotion itself is useful for the class implementer, but doesn't 
help the caller.  Named parameters helps the caller, but doesn't really help 
the class implementer.  The combination of both of them together gives us 
something similar to the object-initializer syntax as a net result, but with 
many other benefits because it's not a one-off syntax.

So with the two of them together, you get:

class Point {
  public function __construct({public int $x, public int $y});
}

Which then allows any of these construction mechanisms:

$p1 = new Point(5, 7);
$p2 = new Point({x: 5, y: 7});
$p3 = new Point({y: 7, x: 5});

All of which result in an object you can use the same way:

print $p1->x . ', '.  $p1->y;

> > * Named parameters
> This one is tricky -- there are tradeoffs of every approach I've seen
> proposed. I have an idea for another way to address this space, but it
> too has drawbacks; there's inherently no free lunch here, I think.

Please share.  I make no claim of being fully versed in the implementation 
details of how these would work at the engine level, only at the syntax level.

> > * Compound Property Visibility
> What is this last one? I searched for "compound" in the article, but
> did not get many hits, none of which described what it actually _is_.

Mm, yeah, I sorta changed names on that part way through.  That's the 
"different visibility for read and for write" proposal that Nicolas mentioned 
in the readonly thread, for which I borrowed the syntax from the property 
accessors RFC.

On Mon, Mar 23, 2020, at 1:07 AM, Mike Schinkel wrote:

> 1. Your post mentions validation needed for value objects — a concern I 
> share — but AFAICT your conclusion does not address the issue.

It doesn't directly in a syntactic way.  Rather, it allows the constructor and 
Setter/Wither methods to still exist as now, and users can write what they want 
in there.  That is, it's no change from now.  That was one of my evaluation 
criteria: Improve as many of these as possible without making any of them 
worse..  This is one were "nothing is made worse".

> 2. It also mentions overlapping concerns and references numerous RFCs, 
> but there were two other relative works not mentioned. One[1] is an RFC 
> and the other[2] a PR on Github. I think they both overlaps with this 
> problem space, with the former addressing validation whereas the latter 
> case potentially conflicts with constructor promotion.

You are correct, I forgot about the impact of annotations (which I also 
support).  Off hand, I think their only issue would be in relation to the 
constructor promotion, as the resulting syntax to put a bunch of annotations 
inside the constructor definition would get... silly.

That suggest we may want a different syntax for constructor promotion than what 
I proposed we borrow from Hack, but I don't think changes the overall argument.

> 1. You don't really address the value object vs. service object 
> distinction, except on the periphery.

Correct.  This also ties into your discussion of Structs/Records as an 
alternative approach.  I have considered that before, but in this writeup... I 
found nowhere that any of the possible implementations would be useful only for 
one or the other.  Rather, certain features may be more useful to one or the 
other but would definitely have uses in both.

At the end of the day, I think the only language-level difference between a 
value and service object is the passing semantics; service objects should pass 
as they do now, while value objects would, ideally, pass in a way more similar 
to arrays.  However, that was off topic at this time, and not needed.  
Everything else discussed would be applicable to both object types, so 
splitting the syntax would not be helpful, just confusing.

For instance, property accessor methods on a new Struct type would have the 
exact same performance issue as they would on a Class today.

The goal was to focus on the minimum amount of work we can do to get the 
maximum benefit, and I don't think a new Struct type would qualify for that.

> 2. You mention the concerns about exposing parameter names as part of 
> the API but don't address those concerns directly.

I do.  Specifically, making named parameters opt-in allows 
class/function/method authors to decide if they want to make their parameter 
names part of the API or not.  The alternative to support it on all callables 
period, which is also a viable option but, as noted in the writeup, technically 
a BC change.  Either approach is possible.

Now that I think about it, though, named parameters and variadics may not play 
nicely at all, so we may want to force it to be opt-in only (and incompatible 
with variadics).

> 3. You mention get/set properties surprisingly running code but do not 
> address those concerns directly.

That's only an issue with full property accessors, which I specifically do not 
propose we implement at this time.  I was trying to represent the arguments 
against property accessors last time, as I remembered them; I personally don't 
think it's a problem and would love to have property accessors exactly as 
described in the RFC, if the performance issues could be resolved.

Since that's not what is being proposed, determining if that's even an issue is 
not within scope.

> 4. Your concept for a JSON object-like syntax for passing parameter 
> feels incomplete to me. Unless I miss understand it is just a special 
> syntax that only works in the context of passing arguments to a 
> constructor, method or function, and not a first-class language 
> element. If we were to go that route I think we would find it highly 
> limiting.

The JSON-esque syntax was one of the options previously discussed the last time 
named parameters came up.  I am not wedded to it, it was just the most 
readily-available way to demonstrate named params being opt-in.  If we make 
them not opt-in, then there is no need for a special syntax at all.

I was very specifically NOT trying to propose a Javascript-like Object Literal 
syntax.  It's just one option among many for denoting a named parameters call.  
So, yes, it only works in the context of passing arguments, by design, that's 
the point.

> 5. In the section you say that "either of the following construction 
> styles becomes possible" but you do not talk about the option of having 
> one of more of the first parameters being positional and the rest being 
> able to be passed by name, which I think would be an ideal use-case 
> when you want to force certain parameters to always be passed but make 
> the rest optional.

Incorrect.  I specifically say in one of the notes that we could consider it, 
but it's not necessary and may be more trouble than it's worth.  It's more 
in-the-weeds than I wanted to get at this stage.

Specifically:

"We can consider mixing positional and named parameters the way Python does, 
but I don't think that's necessary."

 Regarding interaction with Delegation (a la Go, which I also agree is a very 
nice feature and we wants it, precious), I'm not sure.  I would have to defer 
to Nikita for how that would interact with constructor promotion.  Between that 
and annotations we may well want to explore a different syntax than Hack, but 
the essential concept is the same.

> 2. Going further with constructor promotion, which you join with named 
> parameters, how are the parameters represented inside the 
> constructor/method/function?  As different variables methods just like 
> current parameters?  Is there no concept of automatic aggregation of 
> those parameters into some kind of structure that could then be passed 
> down to other methods and functions?

Yes there is; it's called $this.  The whole point of constructor promotion is 
that it avoids you writing 

$this->a = $a;
$this->b = $b;
$this->c = $c;

One possible implementation in fact is to simply auto-generate those exact op 
codes in the source as it's getting parsed.  If you want to then add additional 
logic in the constructor body that would run after those assignments, cool, 
those still work, and the corresponding properties are already populated for 
you to use if needed.

--Larry Garfield

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

Reply via email to