<p>Some languages offer the feature of properties, different from normal member variables, that trigger some code when you read from or write to the property. The triggered code are called accessors. The basic form would have the <code>get</code> and <code>set</code> accessors. Some languages support more.</p>
<p>They usually work for primitive types, like integers, and objects as a whole, usually in reference types (in contrast of value types). But the <code>set</code> accessor is usually not used when you set a subelement of the property. For example, if you have a <code>Point</code> class with members <code>int x,y</code>, and a property <code>Point p</code>, no accessors would be called when <code>p.x = ...;</code> is called. This question is about supporting calling some accessors even if only a subelement is being modified.</p>
<p>It could possibly be simulated by defining a variant of <code>Point</code>, that the members <code>x</code> and <code>y</code> are also properties. But it sounds like it will open a can of worms.</p>
<p>Are there languages having solutions to this, either with features capturing writes on subelements, or features making creating variants of a type with members changed to properties easier, or something else?</p>

<object-oriented><properties>
Were there attempts to support triggering accessors on modifying subelements of properties?
CC BY-SA 4.0
2023-08-30T11:25:58.963Z
I don't know of anything like this, and it would seem to get complicated, e.g. how do I say in class `A` whether to react to `a.b.c.d.e.f.g.x = ...;`? Generally in object-oriented programming, if an object wants to control accesses to its constituent objects then it hides those objects and exposes methods like `setPointX(...)` so that (1) the caller can't set the property without the outer object knowing about it, and (2) it's clear the caller is invoking some behaviour on the outer object.
kaya3
CC BY-SA 4.0
2023-08-30T11:29:48.050Z
I think there would also be complications when both `A` and `B` have code which triggers on accessing `B.x`, does `A`'s code go first, or does it override `B`'s code? Do accesses from within `A` also trigger `A`'s code, and if so `A`'s accessor for `B.x` will need some way of ignoring that so that it doesn't recurse by accident. So there seem to be a lot of problems with this feature.
kaya3
CC BY-SA 4.0
2023-08-30T11:33:49.940Z
One situation where I can imagine it working is in a language where all objects are immutable, so that `a.x = 5` is syntax sugar for `a.withX(5)` (i.e. constructing a new object with a different `x` property), and then `a.p.x = 5` would mean `a.withP(a.p.withX(5))`, and so on. In that case the semantics are clear enough and each class can override `withX`, `withP` and so on as it wishes. It would be illegal to write something like `a.foo().x = 5`, because `a.foo()` isn't an lvalue.
kaya3
CC BY-SA 4.0
2023-08-30T13:04:35.937Z
You can get this functionality in python by returning a proxy object: https://ato.pxeger.com/run?1=m72soLIkIz9vwYKlpSVpuha3GOWScxKLixUcrbgUgCAlNU0hPj4zL7MkPl6jODUnTRMiDgIgrl6Fgq2CIRdYzKGgKL8gtaikEsyDGFOQn5lXgtCCYZyOQkFiUWpeiaYVxDgID2gmhAHXiGo2zKgKdCfBnQXRDnSdNsh5yNJFqSWlRXmoqri4EoFWOmpochUUAd2rkagHdrdeBaYAJJigoQULNQA Something similar is possible in JS and I'm sure many others
mousetail 'he-him'
CC BY-SA 4.0
2023-08-30T15:21:01.670Z
Sounds interesting. What use cases do you have in mind? Where'd this be useful? What problems does it solve or help?
Pablo H
CC BY-SA 4.0
2023-08-30T23:45:16.930Z
Common Lisp does something like this: http://www.lispworks.com/documentation/lw51/CLHS/Body/m_defset.htm Sorry that the link is not especially self explanatory. I'll try to write a proper answer if someone doesn't beat me to it. This might not exactly answer your question but it's definitely the closest feature to it that I've seen.
Glenn Willen
CC BY-SA 4.0
2023-08-31T09:38:25.973Z
@GlennWillen Common Lisp SETF typically mutates the place closest to the property that is being modified: `(setf (second (gethash "id" hash)) 3)` would access `hash`, the list associated with key `"id"`, then change the second element of that list, but the hash won't be updated using `PUTHASH` (its not specified, but no implementation does that). However it could be possible to have a different mechanism that does that, ie. make calls to all setters across all the data-structure being traversed.
coredump
<h3>Proxy pattern with bubbling</h3>
<p>There is a solution for this, in the form of proxy patterns or proxy objects. That is, a new object that wraps around normal objects, and <a href="https://en.wikipedia.org/wiki/Proxy_pattern" rel="nofollow noreferrer">provides additional functionality when accessing an object</a>.</p>
<p>The root wrapping object is responsible to intercept the <em>first</em> property access, and then call specific methods on wrapped objects. On this call, the wrapped object can make computations and then let or interrupt the propagation of this &quot;wrapped coordination&quot;.</p>
<p>If the propagation is not interrupted, the root wrapping object then instantiates a wrapping object of accessed property, calls this wrapping property object, and so on.</p>
<p>With this interfaces, is possible to implement several types of coordination between objects:</p>
<ul>
<li><p><strong>The root knows all:</strong> All processing occurs on the root or parent node, that thens interrupts the propagation.</p>
</li>
<li><p><strong>The leaf call back:</strong> No processing occurs in intermediary wrapped objects, but leaf objects receive a reference to the root object, and then can call back informing them about any leaf mutation.</p>
</li>
</ul>
<pre class="lang-cs prettyprint-override"><code>// Model object

partial class DtoEntity
{
    public Type Property { get; set; }
}

// Control object

partial class DtoEntity : Lang.Mvc.Proxy
{
    // General, untyped proxy.
    // The accumulated call path is in path.
    // The get/set value is in the leaf.
    // Return true to indicate a consumed
    // event (interrupt propragation)
   
    bool ProxyGetValue( string[] path , object root , out object leaf )
    { }
    bool ProxySetValue( string[] path , object root , object leaf )
    { }
}

// Mixed model and control object
// (also, attribute/typed example)

class DtoAnother
{
    [ProxyPropertyLeaf(this.InternalGet, this.InternalSet)]
    public Type Property { get; set; }
   
    bool InternalGet( string[] path , object root , out Type value )
    { }
    void InternalSet( string[] path , object root , Type value )
    { }
}

// Normal objects, no change in compiler

var ent = new Entity();

// Proxy objects
//
// The compiler generate it as
//     class CompileGeneratedN : Entity
// and generates an override for every
// method and property access of Entity
// on the generated Proxy class.
//
// Something like a derived, compile time
// System.Dynamic.ExpandoObject() that
// implements the interface of Entity

var controlEnt = new Lang.Mvc.Proxy&lt;Entity&gt;();
</code></pre>
<p>The functionality of <code>Lang.Mvc.Proxy</code> is not trivial, and can be very slow. It will need to control <a href="https://javascript.info/bubbling-and-capturing" rel="nofollow noreferrer">capture e bubbling algoritm</a>, and also need to remember every called object to avoid cyclic references.</p>

CC BY-SA 4.0
2023-08-30T14:43:26.220Z
2023-09-01T15:10:11.880Z
2023-09-01T15:10:11.880Z
André L F S Bacci
<p>This feature would violate the <a href="https://en.wikipedia.org/wiki/Principle_of_compositionality" rel="nofollow noreferrer">principle of compositionality</a>, which holds that the meaning of a term is derived from the meanings of its subterms. Consider the following two snippets:</p>
<pre class="lang-java prettyprint-override"><code>obj.p.x = 5;
</code></pre>
<pre class="lang-java prettyprint-override"><code>Point p = obj.p;
p.x = 5;
</code></pre>
<p>These two snippets ought to mean the same thing (assuming the local variable <code>p</code> isn't used anywhere else). But with your proposed feature, the first snippet is supposed to trigger <code>obj</code>'s setter for <code>obj.p.x</code>, whereas the second snippet triggers <code>obj</code>'s getter for <code>obj.p</code> and then <code>p</code>'s setter for <code>p.x</code>. That is, a simple refactor to use a temporary variable for an intermediate result, would change the behaviour of this program.</p>
<p>Otherwise, <code>p</code> has to remember that it &quot;came from&quot; <code>obj</code>, and notify <code>obj</code> when any mutation is made through it. In other words, <code>p</code>'s type is not really <code>Point</code>, it's some synthetic subclass of <code>Point</code> which holds a reference to <code>obj</code> and notifies it when <code>x</code> changes. Either it's a proxy object which holds a reference to <code>obj</code> and <code>obj.p</code> and coordinates accesses and mutations with both, or <code>obj.p</code> itself is an instance of that synthetic subclass.</p>
<p>But that probably still doesn't do what you want, because it makes <code>p</code> responsible for the access's behaviour, not <code>obj</code>; <code>obj</code> can't decide to make the mutation conditional (unless there is some more complex protocol whereby <code>p</code> notifies <code>obj</code> before the mutation and <code>obj</code> has the chance to suppress it). You'd also have to worry about <code>obj</code> accidentally notifying itself when it internally mutates <code>p</code>.</p>
<hr />
<p>I think if you want the outer object to know about changes to its component, there are two decent ways to achieve this:</p>
<ul>
<li>If you want <code>obj</code> to be responsible for what happens when someone wants to update <code>obj.p</code>, then <a href="https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)" rel="nofollow noreferrer">encapsulation</a> is the way to go. The caller shouldn't get direct access to <code>obj.p</code>, rather the outer object should have a <code>setPointX</code> method (or a settable <code>pointX</code> property) which can do whatever the outer class wants it to do.</li>
<li>Alternatively, if you want the <code>Point</code> class to be responsible, and you just want <code>obj</code> to get a chance to react to its point being updated (e.g. to maintain some invariant), <a href="https://en.wikipedia.org/wiki/Event-driven_programming" rel="nofollow noreferrer">event-driven programming</a> is a decent alternative. Give the <code>Point</code> an <code>onXChanged</code> event, and let the outer object subscribe to that event.</li>
</ul>
<p>Either of these approaches has the benefits of not needing any novel language features, being easier to understand the semantics of, and being familiar to users.</p>
<hr />
<p>That said, I think the feature is salvageable, just not in an imperative object-oriented language. Consider a pure functional language, with immutable objects. A common pattern in such languages is that when updating a subproperty you have to create new instances of the outer objects, too:</p>
<pre class="lang-js prettyprint-override"><code>let objWithUpdatedPointX = obj.withP(obj.p.withX(5));
</code></pre>
<p>It could be convenient to have syntax sugar like <code>p with .x = 5</code> for <code>p.withX(5)</code>, or <code>obj with .p.x = 5</code> for <code>obj.withP(obj.p.withX(5))</code>. This doesn't violate compositionality, because the <code>.x</code> and <code>.p.x</code> parts aren't expressions and don't have meanings outside of this language construct. In particular, they must be a chain of property accesses, so e.g. <code>obj with .foo().x = 5</code> is not allowed.</p>
<p>In this case, updating the subcomponent necessarily invokes the <code>withP</code> method on the outer object. So you could allow the outer class to override the <code>withP</code> method, in order to do whatever else it needs to do when its component is updated. However, this way the outer class doesn't get to see the value <code>5</code>, only the new <code>Point</code> object. So it would allow for a limited version of what you're thinking of, albeit in a different paradigm.</p>

CC BY-SA 4.0
2023-08-30T12:29:44.593Z
2023-08-30T14:25:33.403Z
2023-08-30T14:25:33.403Z
kaya3
CC BY-SA 4.0
2023-08-30T12:48:34.453Z
@G.Sliepen Well, the same argument would apply to `int x = 5; x = 6;` violating compositionality because `x = 6` doesn't mean the same as `5 = 6`. The difference is that in `obj.p.x = 5`, `obj.p` is an expression producing an rvalue whereas `obj.p.x` is an expression producing an lvalue, and rvalues can be stored in variables (so the refactoring is legitimate) whereas lvalues can't. I do understand your point; you could define the `obj.p` in `obj.p.x = 5` to also be an lvalue, but I think that's an abuse of terminology; `obj.p`'s role in that expression is not as a variable being assigned to.
kaya3
CC BY-SA 4.0
2023-08-30T12:52:13.810Z
Perhaps there is a way to formalise it so that it is compositional. But I think it would still at least violate users' *expectations* of compositionality.
kaya3
CC BY-SA 4.0
2023-08-30T13:11:36.213Z
`int x = p.x; x = 6;` and `int x = 5; x = 6;` could be defined to not violate compositionality, if we change x to a reference. I had ideas of extending references to support properties, but thought it's better to start to work on that only after fully understanding what properties should be.
user23013
CC BY-SA 4.0
2023-10-21T04:58:38.400Z
If the [J obverse](https://code.jsoftware.com/wiki/Vocabulary/codot) supported recovering lost information, the `with` operator could be implemented using [under](https://code.jsoftware.com/wiki/Vocabulary/ampdotco).
user23013
# Were there attempts to support triggering accessors on modifying subelements of properties?
Posted by: username_0 on 2023-08-30
Some languages offer the feature of properties, different from normal member variables, that trigger some code when you read from or write to the property. The triggered code are called accessors. The basic form would have the `get` and `set` accessors. Some languages support more.

They usually work for primitive types, like integers, and objects as a whole, usually in reference types (in contrast of value types). But the `set` accessor is usually not used when you set a subelement of the property. For example, if you have a `Point` class with members `int x,y`, and a property `Point p`, no accessors would be called when `p.x = ...;` is called. This question is about supporting calling some accessors even if only a subelement is being modified.

It could possibly be simulated by defining a variant of `Point`, that the members `x` and `y` are also properties. But it sounds like it will open a can of worms.

Are there languages having solutions to this, either with features capturing writes on subelements, or features making creating variants of a type with members changed to properties easier, or something else?
**Tags:** object-oriented properties
> **Comments:**
> **username_1**: I don't know of anything like this, and it would seem to get complicated, e.g. how do I say in class `A` whether to react to `a.b.c.d.e.f.g.x = ...;`? Generally in object-oriented programming, if an object wants to control accesses to its constituent objects then it hides those objects and exposes methods like `setPointX(...)` so that (1) the caller can't set the property without the outer object knowing about it, and (2) it's clear the caller is invoking some behaviour on the outer object.  
> **username_1**: I think there would also be complications when both `A` and `B` have code which triggers on accessing `B.x`, does `A`'s code go first, or does it override `B`'s code? Do accesses from within `A` also trigger `A`'s code, and if so `A`'s accessor for `B.x` will need some way of ignoring that so that it doesn't recurse by accident. So there seem to be a lot of problems with this feature.  
> **username_1**: One situation where I can imagine it working is in a language where all objects are immutable, so that `a.x = 5` is syntax sugar for `a.withX(5)` (i.e. constructing a new object with a different `x` property), and then `a.p.x = 5` would mean `a.withP(a.p.withX(5))`, and so on. In that case the semantics are clear enough and each class can override `withX`, `withP` and so on as it wishes. It would be illegal to write something like `a.foo().x = 5`, because `a.foo()` isn't an lvalue.  
> **username_2**: You can get this functionality in python by returning a proxy object: https://ato.pxeger.com/run?1=m72soLIkIz9vwYKlpSVpuha3GOWScxKLixUcrbgUgCAlNU0hPj4zL7MkPl6jODUnTRMiDgIgrl6Fgq2CIRdYzKGgKL8gtaikEsyDGFOQn5lXgtCCYZyOQkFiUWpeiaYVxDgID2gmhAHXiGo2zKgKdCfBnQXRDnSdNsh5yNJFqSWlRXmoqri4EoFWOmpochUUAd2rkagHdrdeBaYAJJigoQULNQA Something similar is possible in JS and I'm sure many others  
> **username_3**: Sounds interesting. What use cases do you have in mind? Where'd this be useful? What problems does it solve or help?  
> **username_4**: Common Lisp does something like this: http://www.lispworks.com/documentation/lw51/CLHS/Body/m_defset.htm Sorry that the link is not especially self explanatory. I'll try to write a proper answer if someone doesn't beat me to it. This might not exactly answer your question but it's definitely the closest feature to it that I've seen.  
> **username_5**: @GlennWillen Common Lisp SETF typically mutates the place closest to the property that is being modified: `(setf (second (gethash "id" hash)) 3)` would access `hash`, the list associated with key `"id"`, then change the second element of that list, but the hash won't be updated using `PUTHASH` (its not specified, but no implementation does that). However it could be possible to have a different mechanism that does that, ie. make calls to all setters across all the data-structure being traversed.  
---
## 2 answers
### Answer by username_1 on 2023-08-30. Score: 7 | Accepted answer
This feature would violate the principle of compositionality, which holds that the meaning of a term is derived from the meanings of its subterms. Consider the following two snippets:
obj.p.x = 5;

Point p = obj.p;
p.x = 5;

These two snippets ought to mean the same thing (assuming the local variable p isn't used anywhere else). But with your proposed feature, the first snippet is supposed to trigger obj's setter for obj.p.x, whereas the second snippet triggers obj's getter for obj.p and then p's setter for p.x. That is, a simple refactor to use a temporary variable for an intermediate result, would change the behaviour of this program.
Otherwise, p has to remember that it "came from" obj, and notify obj when any mutation is made through it. In other words, p's type is not really Point, it's some synthetic subclass of Point which holds a reference to obj and notifies it when x changes. Either it's a proxy object which holds a reference to obj and obj.p and coordinates accesses and mutations with both, or obj.p itself is an instance of that synthetic subclass.
But that probably still doesn't do what you want, because it makes p responsible for the access's behaviour, not obj; obj can't decide to make the mutation conditional (unless there is some more complex protocol whereby p notifies obj before the mutation and obj has the chance to suppress it). You'd also have to worry about obj accidentally notifying itself when it internally mutates p.

I think if you want the outer object to know about changes to its component, there are two decent ways to achieve this:

If you want obj to be responsible for what happens when someone wants to update obj.p, then encapsulation is the way to go. The caller shouldn't get direct access to obj.p, rather the outer object should have a setPointX method (or a settable pointX property) which can do whatever the outer class wants it to do.
Alternatively, if you want the Point class to be responsible, and you just want obj to get a chance to react to its point being updated (e.g. to maintain some invariant), event-driven programming is a decent alternative. Give the Point an onXChanged event, and let the outer object subscribe to that event.

Either of these approaches has the benefits of not needing any novel language features, being easier to understand the semantics of, and being familiar to users.

That said, I think the feature is salvageable, just not in an imperative object-oriented language. Consider a pure functional language, with immutable objects. A common pattern in such languages is that when updating a subproperty you have to create new instances of the outer objects, too:
let objWithUpdatedPointX = obj.withP(obj.p.withX(5));

It could be convenient to have syntax sugar like p with .x = 5 for p.withX(5), or obj with .p.x = 5 for obj.withP(obj.p.withX(5)). This doesn't violate compositionality, because the .x and .p.x parts aren't expressions and don't have meanings outside of this language construct. In particular, they must be a chain of property accesses, so e.g. obj with .foo().x = 5 is not allowed.
In this case, updating the subcomponent necessarily invokes the withP method on the outer object. So you could allow the outer class to override the withP method, in order to do whatever else it needs to do when its component is updated. However, this way the outer class doesn't get to see the value 5, only the new Point object. So it would allow for a limited version of what you're thinking of, albeit in a different paradigm.
> **Comments:**
> **username_1** (2023-08-30): @G.Sliepen Well, the same argument would apply to `int x = 5; x = 6;` violating compositionality because `x = 6` doesn't mean the same as `5 = 6`. The difference is that in `obj.p.x = 5`, `obj.p` is an expression producing an rvalue whereas `obj.p.x` is an expression producing an lvalue, and rvalues can be stored in variables (so the refactoring is legitimate) whereas lvalues can't. I do understand your point; you could define the `obj.p` in `obj.p.x = 5` to also be an lvalue, but I think that's an abuse of terminology; `obj.p`'s role in that expression is not as a variable being assigned to.  
> **username_1** (2023-08-30): Perhaps there is a way to formalise it so that it is compositional. But I think it would still at least violate users' *expectations* of compositionality.  
> **username_0** (2023-08-30): `int x = p.x; x = 6;` and `int x = 5; x = 6;` could be defined to not violate compositionality, if we change x to a reference. I had ideas of extending references to support properties, but thought it's better to start to work on that only after fully understanding what properties should be.  
> **username_0** (2023-10-21): If the [J obverse](https://code.jsoftware.com/wiki/Vocabulary/codot) supported recovering lost information, the `with` operator could be implemented using [under](https://code.jsoftware.com/wiki/Vocabulary/ampdotco).  
---
### Answer by username_6 on 2023-08-30. Score: 3
Proxy pattern with bubbling
There is a solution for this, in the form of proxy patterns or proxy objects. That is, a new object that wraps around normal objects, and provides additional functionality when accessing an object.
The root wrapping object is responsible to intercept the first property access, and then call specific methods on wrapped objects. On this call, the wrapped object can make computations and then let or interrupt the propagation of this "wrapped coordination".
If the propagation is not interrupted, the root wrapping object then instantiates a wrapping object of accessed property, calls this wrapping property object, and so on.
With this interfaces, is possible to implement several types of coordination between objects:

The root knows all: All processing occurs on the root or parent node, that thens interrupts the propagation.

The leaf call back: No processing occurs in intermediary wrapped objects, but leaf objects receive a reference to the root object, and then can call back informing them about any leaf mutation.


// Model object

partial class DtoEntity
{
    public Type Property { get; set; }
}

// Control object

partial class DtoEntity : Lang.Mvc.Proxy
{
    // General, untyped proxy.
    // The accumulated call path is in path.
    // The get/set value is in the leaf.
    // Return true to indicate a consumed
    // event (interrupt propragation)
   
    bool ProxyGetValue( string[] path , object root , out object leaf )
    { }
    bool ProxySetValue( string[] path , object root , object leaf )
    { }
}

// Mixed model and control object
// (also, attribute/typed example)

class DtoAnother
{
    [ProxyPropertyLeaf(this.InternalGet, this.InternalSet)]
    public Type Property { get; set; }
   
    bool InternalGet( string[] path , object root , out Type value )
    { }
    void InternalSet( string[] path , object root , Type value )
    { }
}

// Normal objects, no change in compiler

var ent = new Entity();

// Proxy objects
//
// The compiler generate it as
//     class CompileGeneratedN : Entity
// and generates an override for every
// method and property access of Entity
// on the generated Proxy class.
//
// Something like a derived, compile time
// System.Dynamic.ExpandoObject() that
// implements the interface of Entity

var controlEnt = new Lang.Mvc.Proxy();

The functionality of Lang.Mvc.Proxy is not trivial, and can be very slow. It will need to control capture e bubbling algoritm, and also need to remember every called object to avoid cyclic references.
---
