Stream: beginners

Topic: Is there anyway to pass optional parameters to a function?


view this post on Zulip Ashley Davis (Jul 16 2024 at 22:32):

I have the following function that I'm using to create fake gallery items for testing:

# Makes a gallery item for testing.
makeDefaultItem : _ -> GalleryItem
makeDefaultItem = \_ -> {
    width: 10,
    height: 20,
    headings: []
}

I'd like to extend it to include optional parameters to configure it.

In TypeScript I'd do something like this:

function makeDefaultItem({ width?: number, height?: number, headings?: string[] }): GalleryItem {
    return {
        width: width !== undefined ? width : 10,
        height: height !== undefined ? height : 20,
        headings: headings !== undefined ? headings : [],
    };
}

This way I can create gallery items for testing specifying the parameters I care about and defaulting the rest. Say for example my next test really only cares about the width of a gallery item, so in TypeScript I could create it like this:

const galleryItem = makeDefaultItem({ width: 32 });

Is it possible to have optional parameters like this for a Roc function?

view this post on Zulip Luke Boswell (Jul 16 2024 at 22:40):

Here's a demo of the syntax

app [main] {
    cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
}

import cli.Stdout
import cli.Task exposing [Task]

main : Task {} _
main =

    one : GalleryItem
    one = makeDefaultItem {}

    two : GalleryItem
    two = makeDefaultItem {
        width: 100,
        height: 200,
        headings: ["a", "b", "c"],
    }

    Stdout.line! (Inspect.toStr one)
    Stdout.line! (Inspect.toStr two)

GalleryItem : {
    width: U64,
    height: U64,
    headings: List Str,
}

makeDefaultItem : { width ? U64, height ? U64, headings ? List Str } -> GalleryItem
makeDefaultItem = \{ width ? 10, height ? 20, headings ? [] } -> {
    width,
    height,
    headings,
}

view this post on Zulip Luke Boswell (Jul 16 2024 at 22:40):

Unfortunately there's a strange compiler bug :ladybug: if we have both calls, either one is happy but together it crashes.

$ roc demo.roc
thread 'main' panicked at crates/compiler/gen_llvm/src/llvm/build.rs:5759:19:
Error in alias analysis: error in module ModName("UserApp"), function definition FuncName("\x10\x00\x00\x00\x00\x00\x00\x00\'\xae\xa4\xef\x8b\xd4\xa4\x87"), definition of value binding ValueId(3): expected type '(((heap_cell, bag<(heap_cell,)>), (), ()),)', found type '((),)'
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

view this post on Zulip Luke Boswell (Jul 16 2024 at 22:47):

I can't get the optional syntax to work... definitely something strange going on.

app [main] {
    cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br",
}

import cli.Stdout
import cli.Task exposing [Task]

main : Task {} _
main =

    items = [
        makeDefaultItem {
            height: 200u64,
            headings: ["A"],
        },
        makeDefaultItem {
            width: 100u64,
            height: 200u64,
            headings: ["a", "b", "c"],
        },
    ]

    items
        |> List.map toStr
        |> Str.joinWith "\n\n"
        |> Stdout.line!

GalleryItem : {
    width : U64,
    height : U64,
    headings : List Str,
}

makeDefaultItem : { width ? U64, height : U64, headings : List Str } -> GalleryItem
makeDefaultItem = \{ width ? 10, height, headings } -> {
    width,
    height,
    headings,
}

toStr : GalleryItem -> Str
toStr = \{ width, height, headings } ->
    headingsStr = Str.joinWith headings ", "
    """
    Gallery Item:
        width: $(Num.toStr width)
        height: $(Num.toStr height)
        headings: $(headingsStr)
    """
$ roc demo.roc
thread 'main' panicked at crates/compiler/gen_llvm/src/llvm/build.rs:5759:19:
Error in alias analysis: error in module ModName("UserApp"), function definition FuncName("\x10\x00\x00\x00\x00\x00\x00\x00F\x93\xd4\x88\xfa\xad\x9b\x90"), definition of value binding ValueId(12): expected type '(((heap_cell, bag<(heap_cell,)>), (), ()),)', found type '(((heap_cell, bag<(heap_cell,)>), ()),)'
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

view this post on Zulip Ashley Davis (Jul 16 2024 at 22:50):

Ok I might steer clear of optional parameters for the moment. Thanks for your help @Luke Boswell

view this post on Zulip Brendan Hansknecht (Jul 16 2024 at 23:29):

Yeah, compiler bug that seems to only allow for one specialization of the function.

view this post on Zulip Brendan Hansknecht (Jul 16 2024 at 23:29):

Cause it should create a different version of the function for each optional configuration used.

view this post on Zulip Brendan Hansknecht (Jul 16 2024 at 23:30):

Probably a case of missing some wiring to tell it to create the function many times instead of specializing it once

view this post on Zulip Brendan Hansknecht (Jul 16 2024 at 23:30):

That said, I am not very familiar with that part of the code, but I would guess it is a relatively small fix.

view this post on Zulip Luke Boswell (Jul 17 2024 at 00:01):

https://github.com/roc-lang/roc/issues/6909

^^^ Issue logged

view this post on Zulip Brendan Hansknecht (Jul 17 2024 at 00:37):

I think we already have https://github.com/roc-lang/roc/issues/6423


Last updated: Jul 06 2025 at 12:14 UTC