Mutating a mutable optional field requires explicit optional value
Given this definition:
type t = {
mutable foo?: int,
}
let x = {foo: 42}
I would expect both these ways of updating the field to work similarly:
let y = {...x, foo: 24}
let () = x.foo = 24 // Error: this has type: int, somewhere wanted: option<int>
Similarly with:
let y = {...x, foo: ?None}
let () = x.foo = ?None // Error: It seems that this record field mutation misses an expression
The way to make the 2 mechanisms work similarly is to always force the use of x.foo = Some(24) which would make optional fields a pain to use.
That inconsistency you notice is the price to pay to avoid having to do that.
Unless there's some other way that was not considered.
The way to make the 2 mechanisms work similarly is to always force the use of
x.foo = Some(24)which would make optional fields a pain to use.
Is that not how it currently works? x.foo = 24 does not compile, x.foo = Some(24) does.
Edit: rephrased OP to make it clearer what errors.
The way to make the 2 mechanisms work similarly is to always force the use of
x.foo = Some(24)which would make optional fields a pain to use.Is that not how it currently works?
x.foo = 24does not compile,x.foo = Some(24)does.Edit: rephrased OP to make it clearer what errors.
I should have said: uniformity would force {...x, foo: Some(24)}.
That makes more sense. Still don't understand what's meaningfully different about them though? Both seem to have the same information available.
I think I haven't really addressed your question. Your question in about inconsistency between mutable and immutable update.
-
Why not design mutable update to behave like immutable update? Had not considered this really. Let's see, one would change syntax and semantics of
x.foo = .... Then I guess this assignment would stop workingx.foo = y.foobut one would need to usex.foo = ?y.foo. Assuming that assignment pattern is a common one, the change would be quite invasive. -
There's the possibility to make these distinctions disappear, paying some other cost for that privilege. If one were to allow passing values of type
twhereoption<t>is expected, then I think all these special cases would go away. The price to pay: more magic that might be surprising to the developers, and some things to think about with polymorphic type inference where you just don't know whether you're injecting into option or not, yet.
Thanks for the explanation.
- Then I guess this assignment would stop working
x.foo = y.foobut one would need to usex.foo = ?y.foo. Assuming that assignment pattern is a common one, the change would be quite invasive.
This is the same with immutable update though, {...x, foo: ?y.foo}. I would think that pattern is much more common. Is there something about mutation that makes it more invasive?
Is there something about mutation that makes it more invasive?
Not sure really.
I guess the overarching feeling is that each choice has a significant weakness.
Something I'd like to see experimenting with would be to e.g. start small and do the following:
- when type checking
x.foo = e, ifeis of manifestly non-option type then promote it to option type.
This means that all would work:
x.foo = 3x.foo = Some(3)x.foo = y.foo
Then play with this solution for a while and assess whether there are issues working with this. If not, one could map the idea further to immutable mutation, pattern matching etc.