Stream: beginners

Topic: ✔ Any way to programmatically add fields to a record?


view this post on Zulip Ian McLerran (May 13 2024 at 04:28):

Is there any way to programmatically build a record, such that various fields may or may not be present?

My reason being I need to do a json encoding on a record, and certain values absolutely must be omitted entirely from the json object for the API to use its default behavior. As such, I want a way to build a record from a base case, and add fields based on a configuration.

# This code will not work, since the `&` operator cannot add fields to a record,
# But this shows the idea of the behavior I'm looking for
buildRequestBody : Client, List Message -> { model: Str, messages: List Message }*
buildRequestBody = \client, messages ->
    { model: client.model, messages }
        |> \body -> when client.providerOrder is
            NoProviderOrder -> body
            ProviderOrder order -> { body & provider: { order } }
        |> \body -> when client.temperature is
            NoTemperature -> body
            Temperature temperature -> { body & temperature }

Any suggestions? Obviously for just 2 options, I could hardcode each permutation, but I anticipate about 8-10 optional fields, which would be a LOT of permutations.

view this post on Zulip Ian McLerran (May 13 2024 at 04:46):

Come to think of it, can an open record even be used as a return type? Maybe that won't even type check...

view this post on Zulip timotree (May 13 2024 at 05:00):

Yeah using an open record as a return type doesn't usually make sense. If you're returning { model: Str, messages: List Message}* you're saying that you're returning a record which contains model, messages, and any other fields that your caller wants the record to contain. Since your caller could ask for fields that you have no way of producing, such a return type can only mean that the function never returns at all, i.e. it's an infinite loop or a crash

view this post on Zulip timotree (May 13 2024 at 05:03):

If you basically want a record where some of the fields are optional, you could make the optional fields a tag union like { model: Str, messages: List Message, provider: [Unspecified, Specified Provider], temperature: [Unspecified, Specified Temperature] }

view this post on Zulip Ian McLerran (May 13 2024 at 05:06):

Problem is that when I encode the record as Json, those are going to be present in the encoded json, and If I include the provider: { order: List Str } in the json, I'm going to get a 400 status error from the API. it must be a valid list, or no entry in the json object at all.

view this post on Zulip Brendan Hansknecht (May 13 2024 at 06:17):

This was definitely discussed before, but I would need to do some searching to dig it up

view this post on Zulip Brendan Hansknecht (May 13 2024 at 06:17):

Fundamentally, it requires opaque types will custom encoding that enables encoding a field as nothing

view this post on Zulip Brendan Hansknecht (May 13 2024 at 06:17):

Might even require some decoder changes.

view this post on Zulip Brendan Hansknecht (May 13 2024 at 06:18):

That or you simply have to build different records, pass them to decode, and remerge code paths when you have a list of bytes.

view this post on Zulip Brendan Hansknecht (May 13 2024 at 06:22):

discussion related to this: #contributing > How to handle json null decoding

view this post on Zulip Luke Boswell (May 13 2024 at 06:46):

Checkout https://github.com/lukewilliamboswell/roc-json/blob/main/package/OptionOrNull.roc

view this post on Zulip Luke Boswell (May 13 2024 at 06:47):

@Eli Dowling implemented Optional for this use case.

view this post on Zulip Luke Boswell (May 13 2024 at 06:49):

We should probably add an example which shows how to do this.

view this post on Zulip Ian McLerran (May 13 2024 at 13:02):

Ah! yes, Option is exactly what I'm looking for. Thanks guys! Brendan, I was really quite afraid that my only option was going to be my own custom encoder. Awesome to see its already included in roc-json. :fire:

view this post on Zulip Notification Bot (May 13 2024 at 17:01):

Ian McLerran has marked this topic as resolved.


Last updated: Jul 06 2025 at 12:14 UTC