Stream: ideas

Topic: anonymous updater sugar instead of optional fields


view this post on Zulip Richard Feldman (Feb 25 2024 at 14:10):

splitting off from this:

Richard Feldman said:

I think it's reasonable to start new threads to discuss alternative designs to optional record fields.

here's a variation on a proposal Dillon Kearns made for Elm, that would be idea for an alternative to optional record fields in Roc:

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:11):

suppose I could write this in Roc:

{ firstName: "Sam", lastName: "Sample", .. }

...and this was syntax sugar for this function:

\rec -> { rec & firstName: "Sam", lastName: "Sample" }

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:11):

so the addition of the .. makes it an updater function

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:11):

and I could do { .. } to get a function with the type {}a -> {}a

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:13):

this would facilitate a pattern where instead of asking for a config parameter like this:

range: { start: Num a, stop : Num a, step ? Num a } -> List (Num a)

...I could do this:

range: (Config a -> Config a) -> List (Num a)
    where Config a : { start : Num a, stop : Num a, step : Num a }

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:15):

I like how this looks at the call site, because the .. explicitly shows that there's potentially information being omitted - I like that compared to the status quo

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:16):

it's also nice to be able to remove a primitive from the language and replace it with syntax sugar, since that simplifies the language

view this post on Zulip Richard Feldman (Feb 25 2024 at 14:19):

it has a few downsides though, including:

view this post on Zulip Brendan Hansknecht (Feb 25 2024 at 15:59):

So take an update function, then apply that to your default record?

view this post on Zulip Brendan Hansknecht (Feb 25 2024 at 15:59):

Use a nice syntax to make the update function convenient to write

view this post on Zulip Richard Feldman (Feb 25 2024 at 16:01):

right

view this post on Zulip timotree (Feb 26 2024 at 07:08):

One downside of this approach is that it seems to require defining defaults for every field of the record. This doesn't align very well with the range use case, because there is no sensible default for stop.

view this post on Zulip Norbert Hajagos (Feb 26 2024 at 10:16):

I don't mind having more language features (as a user of the language, not a compiler implementer), if those features work together nicely withig the language. I always think of go. At first sight the language seemed like it was ducktaped together (Why can't "range" be a userland function? Did you really create so many special cases inside the language, that I could not create myself?). But when I start to use it... It's great. Although it is a separate language feature having a "range" which could have been created utalizing better primitives, it does not make using go harder.
In that spirit, I would stay with the current version compared to the update syntax when discussing default values.

Another important downside: I don't use roc_ls, but I suspect for the current implementation, it is easy to display the default value of a record field when the editor asks for a function signature (hovering over the fn with the mouse for example). With the proposed change, there would be no way to do that. Well, there would, but even writing it down feels silly. We make a very specific rule that sometimes applies, sometimes not like "if the function starts with calling an updater function (defined as only updating record fields) with a record full of default values (compile-time decidable values), treat that record as if it was in the signature...)

view this post on Zulip Norbert Hajagos (Feb 26 2024 at 11:25):

Is it explained somewhere why we do not allow & to add fields to records if not present, not just overwrite it? It would solve timotree 's prev comment and would make it easy to have default values for records, albeit not inside the function signature, which has the same problem as I have described before with the language server no being able to display it.

I am sure it isn't so simple as in a dynamic language like js with it's { hostAt: "localhost", name: "default app name", ...myConf, } syntax. Does it make the code more error prone, is it not possible without extra runtime code, would it need complicated compile time transformations? My first instinct was to write this for roc:

createServerConf = \conf -> { conf & hostAt: "localhost", name: "default app name"}

# provide only the fields i want to overwrite
serverConf = createServerConf {name: "Not the default named app"}

# the hostAt field was added to the cerverConf record.
expect serverConf == {hostAt: "localhost", name: "Not the default named app"}

view this post on Zulip Richard Feldman (Feb 26 2024 at 11:42):

Norbert Hajagos said:

Is it explained somewhere why we do not allow & to add fields to records if not present, not just overwrite it?

it's possible in theory, but we haven't tried implementing it :big_smile:

view this post on Zulip Norbert Hajagos (Feb 26 2024 at 14:30):

Oh, very exciting! If we had that feature, we wouldn't need optional record fields. You could easily have the defaults be an ordinary record and override the fields with a record update from the arguments. But... You would still have to destructure the argument, since recordWithDefaultValues & recordFromArgument is not a valid syntax. You have talked about that already. We are back where I like the current impl better.

view this post on Zulip Brendan Hansknecht (Feb 26 2024 at 18:08):

I personally am not a fan of this much at all. I think it is more verbose and confusing than default valued fields. Also, I think that requiring defaults for everything totally ruins the feature.

view this post on Zulip Kevin Gillette (Mar 10 2024 at 23:25):

This feels a bit too magical to me

view this post on Zulip Kiryl Dziamura (Mar 11 2024 at 02:21):

Here’s another related thread on the possibility of eliminating optional fields in records completely


Last updated: Jun 16 2026 at 16:19 UTC