I wonder if somebody tried creating a language where you can write mutations in a straightforward imperative style, and the compiler transforms the changes automatically to pure, Redux-style actions. For example (pseudo-js):
atomic function repaint_car(car) {
car.color = "Blue"
car.value += 1000
}
would be converted to:
{
type: REPAINT_CAR,
new_color: "Blue",
delta_value: 1000
}
To clarify, I do not expect this to work for arbitrary code of course. You would apply it to a scope of code that mutates one or more plain-old-data (POD) objects. The language or tool would then create an equivalent "action" object.
I think this would help if you want to change something deeply nested in the state. It is often hard in functional programming to construct the new state, but in mutable code you just write state.garage[0].cars.cupholder.color = "blue"
(as an exaggerated example).
You could also convert code to use the command pattern. While not functional, it does contain the mutation of state, and plays a similar role to Redux:
class RepaintCarCommand extends Command {
constructor(color, value) {
this.color = color;
this.value = value;
}
function do(car) {
this.previous_color = car.color;
this.previous_value = car.value;
car.color = this.color;
car.value += this.delta_value;
}
function undo(car) {
car.color = this.previous_color;
car.value = this.previous_value;
}
}
It would also make the transition from simple to complex app easier. If you start with a simple sequential app, and at some point decide to add undo capability, you have to rewrite everything to use the command pattern. This capability would allow you to isolate the mutations, without restructuring the app too much.
Does this idea have a name? Does any language implement this? Or are there reasons why this would be impossible or not a good idea?
(Note: I'm not looking for a language recommendation. This is a question about programming language design. I would like to know if this idea has merit, and hope to learn something about equivalences between mutable and immutable/functional constructs. Please don't close this as a "recommendation" question.)
var car; repaint_car(car); alert(car.Color)
be converted? What you are suggesting is EXTREMELY complex transformation. And simple code snippet is not enough to give full idea what is meant to happen.alert
is defined asscreen.windows.add(MessageBox(caption))
. This can be reversed. Option 2: Compile time error, "function alert is not pure". I am suggesting it to be able to work on plain-old-data objects. I have no expectation to wrapformat_drive()
orfire_missiles()
:-). But for something like "format this span of text bold" or "insert a line into this table", I have done the conversion myself, and it seemed so mechanical that a compiler could do it better.repaint_car
. And to make it much harder, see something like this :var car; car2 = car; repaint_car(car); alert(car2.Color)
state.garage[0].cars.cupholder.color = "blue"
is a massive code smell and shows misunderstanding of OOP design.