Pins
Modeling This as an input pin is a pretty nice idea! We thought of everything else, but now that you mention it I’d say that’s the most promising candidate.
On the application side, each instance operation comes with an Input pin to feed the instance. But not only that: Also in the node browser you see that pin. So it is there on the definition. It is there implicitly. The idea to be able to access this pin on the definition side, within some instance operation sounds pretty straight forward and quite nice. There is also no question arising when that This construct will execute or alike since it is an input pin, which just hands over what got fed to the pin from outside before anything else in the patch body will execute.
In the case of a class, we are always just talking about one mutating instance. But when thinking about records this Input pin would always hand over the unmodified incoming instance, no matter how hard you try to modify your state via writing pads or calling some instance operations on yourself. An input pin reflects this behavior best.
And having that input pin named “Input” (like seen on application side) instead of “This” would even be more precise: In case of a record we avoid any confusion. The “Input” is the incoming state, NOT the outgoing state or the state that is already “half modified” (like: one pad got written already) and will eventually be the outgoing state…
And suddenly also and output pin “Output” makes sense… You typically don’t it, but in some corner cases - especially when calling own instance operations within records - you might want to hand over a new state explicitly: the state output that you got from calling your own instance operation.
Something we need to fix
I attached a patch that makes use of your super nice hack. It is perfect for prototyping that feature.
In the first doc this.vl (18.6 KB) we have SelfRefering object that on update calls Up on itself, the Down and then checks if we are back in the same state as before. That works and everybody is happy. But we didn’t mix pads and calls on our instance.
In the second case this2.vl (29.1 KB) I do mix them and came up with one corner case where the patch suggests that a pad should have been written before splitting its state, but it didn’t.
Writing fields currently is the last thing the machine does before leaving the patch.
One way to fix this is to suddenly disallow pads that are connected upstream and downstream on one operation, which would be like saying: per operation, we only have reading the incoming state and writing the outgoing state, but nothing can be done after that. The language would then adjust to what the target code currently does. It might even be cleaner.
Or, currently still preferred: Keep the language as is, but change the target code and write in the right moment.
Let’s call this one the ThroughPassingPadCaughtWhenNotWritingItsField bug, unrelated to the This feature request as we can already come up with weird patches showing the bug without having the feature.
Still, I’d say this needs to have at least the same priority as we shouldn’t change either the language or the target code after leaving the preview phase.
Soo. After fixing the issue you then would be able to mix writing pads and calling operations on yourself. Is that a readable patch? Maybe, maybe not. Maybe even when this got fixed, you should go for other patterns to get a clean readable patch.
In the search for patterns
I’d like to argue that there are two major ways to touch state data:
- on application side you create some state of an object, you pass that state to the next call. So you always touch that whole object. It’s the bird eyes view onto state.
- inside a stateful patch, you typically don’t want to think about the whole thing, but about parts of it, namely its fields. No need to for splitting the incoming state and joining another for the outgoing state: you make use of pads that allow to directly interact with parts of the state and the language splits the incoming state for you and joins a new state object for you if necessary.
I think these inside and outside views onto state are fundamentally different ways to touch it. And even if we wouldn’t have to bug up there, I think they just can’t really mix well or you shouldn’t try it. Can I get a hand onto the state that got created via writing into this pad. No you can’t. And can’t just take that state, feed it into another operation call of your own type and then read the modified state via a pad…
So I’d say: If you need the outside perspective onto state within some operation. Then try to stick with that way of expression within that operation. If you just want to write or read a field: Introduce a Setter or Getter Operation that does that for you. You now can order all the calls nicely and always stick to the birds-eye perspective.
With your “nice” little hack it should be possible to try this pattern idea already and give some feedback if this is feasible or not. That would be great! Thanks for your help!