Edit: the idea presented in this post was worked out into a consistent language feature and accepted for publication.
Ownership type systems have been designed for statically typed languages to confine and constraint aliasing, which in turn increases security and safety. Ownership type systems are conservative, and can only enforce properties that are known to hold globally and statically.
Rather than taking a static view on ownership, a dynamic view would be more natural–and accurate–and could also be applied to dynamic languages. The pendent of static typing in dynamic languages is testing. Ownership violations would raise run-time errors. The system would need to be tested to ensure it is free of ownership violation. This bears resemblance with contracts, and ownership could be seen as special kind of run-time contracts. Also, similarly to contracts, once the system has been exhaustively tested, run-time ownership checks could be disabled.
The ownership relationship between objects could be changed at run-time. While we can expect that most of the time, the owner of an object remains the same and is known at object creation-time, this must not necessary be the case. Whether an object can have multiple owners or not is an open question. If we restrict the system to one owner per object, the syntax could be as simple as:
anObject := MyClass newOwn. "create a new instance that will be owned by self" anObject := MyClass new ownedBy: anOwner. "assigned an arbitraty owner"
Of course, only an ower that satifies the ownership constraint can be assigned, not any object. Once assigned an owner, the system would enforce no aliasing happen that would violate the ownership constraint. In practice, this means that assignments, and parameter passing must be checked at run-time. This is not trivial without entailing a high overhead in space and time.
Combined with resumable exceptions, ownership violations might not be fatal, and could be considered as special events one can catch when objects escape their owners. For instance, when an object escapes its threads, it could be adapted to become thread-safe, or objects could be frozen (i.e. made read-only) when then escape their owner. An variant would be be able to specify a treatment block per ownership relationship, that would be executed if the constraint is broken. By default, objects would have flag that indicates if the contraints holds (for sure) or not. Raising exception or other strategies would be built on top of that.
MyClass new ownedBy: anOwner ifViolated: aBlock. "treatment if constraint is violated" aFlag := anObject isOwnershipEnforced.
There are few interesting questions around this run-time perspective on ownership:
- Can certains patterns be better expressed with ownership?
- Does the ownership information help program understanding?
- Do objects have one natural owner in practice?
- Do run-time ownership checking help spot bugs or increase safety?
- How can run-time ownership checking be made practical from point of view of performance?
Ah! As usual, more questions than answers…