On Sat, Jul 11, 2020, at 9:06 AM, Olle Härstedt wrote:
> Dear internals,
> 
> I'd like to discuss the concept of ownership in PHP, from the point of
> view of a new interface UniqueInterface (or SplUniqueInterface or
> something), which will throw a UniqueException if refcount > 1.
> 
> Use-case: Mutable objects that cannot be shared (without (deep) cloning).
> 
> Rational: Immutable objects are considered "easier to reason about"
> and generally more safe, and as a way to avoid
> spooky-action-at-a-distance. I argue that mutability is totally fine
> as long as it's not *being shared*. Currently, there's no way to
> enforce this in PHP, *but* PHP has a refcounting GC which could do
> this. This would be a more performant alternative than to build lots
> of immutable objects using $obj->whereSomething('bla') constructs.
> 
> Cons: If PHP switches to tracing GC, it will be unusable.
> 
> What do you think? Should I write it down as an RFC? Implementation
> should be straight-forward, assuming refcount is manipulated at a
> single place in the source.
> 
> Regards
> Olle

I like the goal of addressing shared mutable state is a laudable one and I 
think most here share it.  However, I think uniqueness checking is the wrong 
approach, for reasons others have already explained.

You're correct that the thing to avoid is shared mutable state.  That can be 
avoided either by getting rid of mutable state or shared state.  Either would 
work.  (Channeling Kevlin Henny here.)

In the case of PHP, since we don't have threads to worry about the main source 
of shared state is reference variables, or refrence-esque objects.  (Or 
globals, but I'm assuming most here know to avoid those already.)  That is, 
mutability or shared-ness within a function is, meh, who cares.  It's at 
function boundaries that we care.

As others noted, a ref count check wouldn't help with that much, because the 
act of passing an object to another function necessarily increases the 
refcount, thus eliminating the main benefit.

Rather, the way to eliminate shared-ness is to have "structs," that is, objects 
that pass by value-ish rather than pass-by-reference-ish.  (Yes it's more 
complicated than that, I know, I'm talking about the user-space implications.)  
PHP 4 objects all worked that way, which was a problem for anything with 
services our resources behind it.  That's why it changed in PHP 5 to the more 
common by-ref-ish behavior, which... is a problem for value objects.

Both use cases are valid.  It's why newer languages like Go and Rust take a 
completely different approach to what "object" even means in the first place.

It's been discussed before but never really implemented; I do think the way to 
help break the "shared state" side is to allow objects to get flagged as "will 
use by-value passing" or "will use by-reference passing" (again, implications, 
not implementation).  That is, if you have a by-val object and pass it to a 
function, it behaves the same way as passing a string or an array: 
Copy-on-write of the object when any changes are made to properties of the 
object.  Probably we'd also need to require that properties of by-val objects 
cannot be by-ref objects or resources, which seems reasonable to me.

I think that would do a far better job of addressing the shared-mutable-state 
issue than reference counting, because it attacks the root problem rather than 
a symptom.

--Larry Garfield

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

Reply via email to