On Wed, Aug 31, 2022, at 4:26 PM, Tim Düsterhus wrote: > Hi > > On 8/31/22 22:43, Larry Garfield wrote: >> ## References make everything worse >> >> […] >> >> That problem wouldn't happen if all we're changing is visibility, however. >> That means in the C# style, we would need to differentiate whether the block >> on the right is intended to disable references or not. Ilija has proposed >> `raw` to indicate that. That would mean: >> >> ```php >> class Test >> { >> public $a { private set; } >> public $b { private raw; } >> >> public function inScope() >> { >> echo $this->a; // echo $this->getA(); >> $this->a = 'a'; // $this->setA('a'); >> >> echo $this->b; // echo $this->b; >> $this->b = 'b'; // $this->b = 'b'; >> } >> } >> >> $test = new Test(); >> >> echo $test->a; // echo $test->getA(); >> $test->a = 'a'; // Error, set operation not accessible >> >> echo $test->b; // echo $test->getB(); >> $test->b = 'b'; // Error, set operation not accessible >> ``` >> >> The take-away for the asymmetric visibility only case is that we would need >> to use `raw` instead of `set`, in order to avoid confusion later with >> accessor hooks and whether or not to disable references. >> >> The Swift-style syntax, as it does not require any hook-like syntax to just >> control visibility, does not have this problem. There is no ambiguity to >> resolve, so no need for a `raw` keyword. >> > > I've read through that explanation three times, but don't understand why > the C#-style syntax would require to differentiate between `set` and > `raw`. Isn't the difference between "visibility only" and "accessor" not > clear [1] by having either '{' or ';' after the 'set'? > > [1] Read: Clear to the engine, not talking about the human reader here.
Yeah, it's complicated, and Ilija had to explain it to me several times. :-) The tricky part is that there's *three* different toggles involved here. 1. Asymmetric visibility. 2. Accessor hooks. 3. Disabling references on properties. Invoking 2 necessarily implies also doing 3, for reasons given above. However, we also want people to be able to enable 3 on its own, so that IF they enable accessor hooks later, it is transparent and doesn't imply breaking references unexpectedly. (Viz, you could have a value object full of `public string $foo {}` type properties, which disables references, and then slip in a get/set hook later and no one notices.) So we need a way to indicate "I'm using a-viz, and disabling references" as well as "I'm using a-viz, and not disabling references." With the Swift style syntax, that's super straightforward. public string $foo; // No a-viz, references work. public string $foo {} // No a-viz, references disabled. public private(set) string $foo; // a-viz, references work. public private(set) string $foo {} // a-viz, references disabled. And the {} makes a convenient marker because you'd be adding it in the future anyway if you add hooks, which would force disabling of references. So it's a natural flow from one option to the next. With the C# style, a-viz means you're *always* putting braces on the right, so we cannot do that. Instead, you need public string $foo; // No a-viz, references work. public string $foo {} // No a-viz, references disabled. public string $foo { private raw; } // a-viz, references work. public string $foo { private set; } // a-viz, references disabled. So then the toggle for disabling references is "there's a set or get keyword inside the braces", but we then need a different keyword for "I'm *just* doing a-viz, and I don't want to disable references." Hence, "raw". (I'm assuming in the above that Ilija is able to make omitting the "get; set;" if there's no body for them. He's reasonably sure we can but hasn't confirmed it.) Is that clearer? --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php