I am looking at the encode and decode api rn. One thing I quite dislike is that record and tuple encoding requires manifesting a list. On top of that, the record encoder forces generating a string name, but many encoders (especially for binary formats) will never use the field name. Given the api is getting update, I was thinking it would be good to iron this out as well.
Specifically these 3 functions:
record : List { key : Str, value : Encoder state } -> Encoder state where state implements EncoderFormatting
tuple : List (Encoder state fmt) -> Encoder state where state implements EncoderFormatting
tag : Str, List (Encoder state fmt) -> Encoder state where state implements EncoderFormatting
Can we somehow do this in a polling format where instead of manefesting the list, we load one element at a time. With that we can also separate loading the record field name from loading the record field encoder.
Any thoughts?
Oh, looks like serde has answers again:
add a separate method for encoding fields from encoding the wrapper type.
Then build up the record like so:
let mut rgb = serializer.serialize_struct("Rgb", 3)?;
rgb.serialize_field("r", &self.r)?;
rgb.serialize_field("g", &self.g)?;
rgb.serialize_field("b", &self.b)?;
rgb.end()
Not 100% sure how all the types work out and how this maps, but feels quite doable.
Maybe for roc, this mean that Encode.record
would take a lambda to add fields:
I noticed that we don't actually name our records unlike serde. Not sure if that is something we want to add or not. Given are types aren't nominal, it feels unimportant. Though might matter for opaque types or certain serialization formats?
encodeRgb = \{r, g, b} ->
size = 3
Encode.record "name?" size \state, addField ->
state
|> addField "r" r
|> addField "g" g
|> addField "b" b
hmm, not user that actually would typecheck. Cause each field could have a different type. So each field might need to monomorphize addField
differently.
oh wait, this should work:
encodeRgb = \{r, g, b} ->
size = 3
Encode.record "name?" size \state ->
state
|> Encode.recordField "r" r
|> Encode.recordField "g" g
|> Encode.recordField "b" b
Cause Encode.recordField
can now monomorphize for each field uniquely.
That said, this api still feels off a bit. Maybe it is good though.
Last updated: Jul 06 2025 at 12:14 UTC