Stream: beginners

Topic: record update


view this post on Zulip Artur Swiderski (Apr 21 2023 at 10:13):

I think roc does not allow me to do this :
outStruct = { inStruct : { one: 1 , two : 2 } , something = 0 }
newStruct = { outStruct & inStruct : { outStruct.inStruct & two = 9 } } it should work but apparently it does not

view this post on Zulip Brendan Hansknecht (Apr 21 2023 at 17:01):

So two things are going on here:

First, the syntax is slightly off. The equal signs should be colons:

outStruct = { inStruct : { one: 1 , two : 2 } , something: 0 }
newStruct = { outStruct & inStruct : { outStruct.inStruct & two : 9 } }

Second, updating does not work with nested fields. I feel like it should in a case like this, maybe that is a bug that we need to file.
Specifically the issue is with { outStruct.inStruct & two : 9 }

When put in the repl directly, we print the error:

── SYNTAX PROBLEM ──────────────────────────────────────────────────────────────

This expression cannot be updated:

6│      { outStruct.inStruct & two : 9 }
          ^^^^^^^^^^^^^^^^^^

Only variables can be updated with record update syntax.

view this post on Zulip Brendan Hansknecht (Apr 21 2023 at 17:02):

My gut feeling is that we should support this, but I am not sure the technical changes required for that.

view this post on Zulip Brendan Hansknecht (Apr 21 2023 at 17:03):

A working alternative would be:

outStruct = { inStruct : { one: 1 , two : 2 } , something: 0 }
inStruct = outStruct.inStruct
newStruct = { outStruct & inStruct : { inStruct & two : 9 } }

view this post on Zulip Brendan Hansknecht (Apr 21 2023 at 17:04):

@Folkert de Vries do you know if there is a specific technical reason that we can't support a record update like this:

{ outStruct.inStruct & two : 9 }

view this post on Zulip Folkert de Vries (Apr 21 2023 at 17:04):

because it is unclear what this does

view this post on Zulip Folkert de Vries (Apr 21 2023 at 17:04):

is the return type of this the type of the outer, or the inner struct

view this post on Zulip Brendan Hansknecht (Apr 21 2023 at 17:12):

That makes sense.

view this post on Zulip Brian Carroll (Apr 21 2023 at 18:19):

To me it seems "obviously" the type of the inner struct.. I can't parse it in my head to make it be the outer one

view this post on Zulip Brian Carroll (Apr 21 2023 at 18:20):

Is it "obviously" the other way around for someone else?

view this post on Zulip Brian Carroll (Apr 21 2023 at 18:21):

To me outStruct.inStruct is the expression between { and & so it's the record you're updating

view this post on Zulip Agus Zubiaga (Apr 21 2023 at 18:28):

Yeah, to me, that's as intuitive as the case with the inStruct def

view this post on Zulip Agus Zubiaga (Apr 21 2023 at 18:29):

Elm also doesn't support arbitrary expressions in record update

view this post on Zulip Agus Zubiaga (Apr 21 2023 at 18:29):

and I want them all the time :D

view this post on Zulip Agus Zubiaga (Apr 21 2023 at 18:32):

It doesn't have to be arbitrary expressions, though. Identifiers would be enough.

view this post on Zulip Brendan Hansknecht (Apr 21 2023 at 18:34):

I think this would be something that people would also quickly learn if we added it. Even if they thought the wrong option, they will just get a type mismatch and need to learn how this works once.

view this post on Zulip Artur Swiderski (Nov 03 2023 at 15:11):

Let say there is record
P = { k: { ... } , ... } I can't do { P.k & .... } instead I have to go around f = P.k {f & ...} is that ok ?

view this post on Zulip Brendan Hansknecht (Nov 03 2023 at 15:14):

I don't understand your workaround. Can you elaborate?

view this post on Zulip Richard Feldman (Nov 03 2023 at 18:01):

Artur Swiderski said:

Let say there is record

P = {

hm, P = { isn't valid Roc syntax, because it's capitalized - did you mean exposing a record named k from P.roc?

view this post on Zulip Artur Swiderski (Nov 04 2023 at 13:40):

I meant
p = { k: { ... } , ... }

-- I can't do this
h = { p.k & .... }
-- but I can
f = p.k
h = {f & ...}
-- this a bit unexpected since those are equivalent

view this post on Zulip Agus Zubiaga (Nov 04 2023 at 13:56):

I think this was inherited from Elm where you also can’t use arbitrary expressions in record update

view this post on Zulip Agus Zubiaga (Nov 04 2023 at 13:59):

That said, I’d prefer Roc supported arbitrary identifiers at least. I probably wouldn’t want to put a function call there, but being able to access record fields would be nice.

view this post on Zulip Sky Rose (Nov 04 2023 at 14:25):

Why not allow function calls or any arbitrary expressions?

view this post on Zulip Agus Zubiaga (Nov 04 2023 at 14:41):

Yeah, I mean I wouldn’t be against it really. I just figured the design intention was to keep these simple.

view this post on Zulip Richard Feldman (Nov 04 2023 at 15:52):

would you want that entire { ... } expression to evaluate to the record p (with its k field updated) or to the k record?

view this post on Zulip Brendan Hansknecht (Nov 04 2023 at 15:56):

I think we have a syntax that works for both even if it isn't currently enabled for both:
Update k in p: { p & k: {...}}
Update k only: {p.k & ...} this returns something with the same type as k

view this post on Zulip Richard Feldman (Nov 04 2023 at 17:20):

yeah so I think that could plausibly be supported, but I remember way back when @Folkert de Vries and I were discussing the original implementation, it made something about the type inference significantly trickier. I don't remember the details anymore though. :big_smile:

view this post on Zulip Artur Swiderski (Nov 08 2023 at 13:37):

Richard Feldman said:

would you want that entire { ... } expression to evaluate to the record p (with its k field updated) or to the k record?

intuitively to the 'k' record

view this post on Zulip Artur Swiderski (Dec 20 2023 at 15:51):

I hope there is plan to do something about this because I stumbled upon this again


Last updated: Jul 06 2025 at 12:14 UTC