Re: [RFC] Asymmetric visibility
| From: | Larry Garfield | Date: | Wed, 31 Aug 2022 23:58:45 +0000 |
| Subject: | Re: [RFC] Asymmetric visibility | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-118550@lists.php.net to get a copy of this message | ||
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