Hi all,
OCaml and pretty much most functional languages have a handy feature, which makes sense to call “functional record update” or a “with-expression”.
An update would just be: { record with my_fields }. Copying all the fields in a record and producing a new record where some values are different.
We could also manually desconstruct and reconstruct a record like:
let {x; y; width; height} = square in
{x + 5; y + 5; width; height}
Manually deconstructing and reconstructing records like that is more tedious boilerplate (especially for large records!), but it comes with an advantage: if you add a new field (like, say, z_index: int), you will receive a type error that the new field is missing. That can be a useful reminder if you also want z_index to have a new value in the updated record.
There is a trade-off between ease-of-writing and ease-of-maintaining here. It is easier to read and write with-expressions, but the type errors you get from the manual way could save frustrating hours of debugging as well.
I think I prefer with-expressions in languages that support them, like OCaml and Elm, but I’m second-guessing myself after performing a refactroring in Standard ML (which lacks with-expressions) yesterday and being happy that the compiler caught a bug I would have otherwise introduced.
I would be happy to hear your thoughts about how you approach the dilemma! Do you always use with-expressions, always use the manual method (probably no one here does that because of the boilerplate) or do you have some criteria that you prefer one or the other?
Maybe I’m overthinking since those in the procedural camp also don’t have type errors when introducing new fields
but I would be happy to hear others’ opinions as well.