Stream: beginners

Topic: "Closing Parenthesis Next"


view this post on Zulip Tobias Steckenborn (Jul 06 2025 at 14:16):

Hey there,

Could one of you help me understand why at the place below there's a complaint about I was expecting to see a closing parenthesis next, so try adding a ) and see if that helps?? Trying to update some old code

    result = List.walk_with_index_until(
        instruction_as_floor_changes,
        (starting_floor, 0),
        |state, instruction, index| # <------------ HERE
                floor_number = state.0
                if floor_number == target_floor {
                Break((floor_number, index))
                } else {
                Continue((Num.add(floor_number, instruction), index))
                }
)

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:19):

we should try to improve that error message, but what it wants is for an { right where # <----------- HERE is, and then a corresponding } later (so, the last two characters of the snippet would become })

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:20):

the reason is that now when you have an inline assignmenet like floor_number = state.0, you wrap the whole thing in curly braces

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:20):

(we used to do it with significant indentation and now we do it with curly braces)

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:20):

so the updated version would be:

    result = List.walk_with_index_until(
        instruction_as_floor_changes,
        (starting_floor, 0),
        |state, instruction, index| {
                floor_number = state.0
                if floor_number == target_floor {
                Break((floor_number, index))
                } else {
                Continue((Num.add(floor_number, instruction), index))
                }
        }
)

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:21):

actually, I just remembered - this is true in the new compiler, but I'm actually not 100% sure we backported that change in the current release of the compiler :sweat_smile:

view this post on Zulip Tobias Steckenborn (Jul 06 2025 at 14:22):

Okay, what really confused me - and now I don't know if that's because I maybe left the program in a half running half incorrect state - that e.g. here:

floor_determination = |instructions, starting_floor|
    instruction_as_floor_changes = instructions |> Str.replace_each("(", "1,") |> Str.replace_each(")", "-1,") |> Str.split_on(",") |> List.keep_oks(Str.to_i32)

    resulting_floor = List.walk(
        instruction_as_floor_changes,
        starting_floor,
        |floor_number, instruction|
            Num.add(floor_number, instruction),
    )

    Num.to_str(resulting_floor)

I had to remove the curly braces.

Didn't really help that the VSCode Plugin seems to break / not show anything when there's a single error and same with the formatting :D

view this post on Zulip Tobias Steckenborn (Jul 06 2025 at 14:23):

Richard Feldman schrieb:

actually, I just remembered - this is true in the new compiler, but I'm actually not 100% sure we backported that change in the current release of the compiler :sweat_smile:

Well in atleast what I downloaded that also complains :D

view this post on Zulip Tobias Steckenborn (Jul 06 2025 at 14:23):

Prefer the brackets in general though. Yet likely just because I'm used to it.

view this post on Zulip Tobias Steckenborn (Jul 06 2025 at 14:24):

So with a nix flake just installed today (roc.url = "github:roc-lang/roc";) your version also doesn't work (when I just copied it in). Doesn't really help that roc version here just says roc built from source though :sweat_smile:.

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:31):

hrm, ok @Anton might have a better idea then?

view this post on Zulip Richard Feldman (Jul 06 2025 at 14:31):

(I've been so immersed in the new compiler that I've lost track of what's in the stable version, really sorry about that!)

view this post on Zulip Tobias Steckenborn (Jul 06 2025 at 14:39):

I'd assume it's got something to do with the second parameter that's passed in as that's the only difference to the other function that apparently works. So likely the tuple is the problem somehow.

Works:

find_last_floor_entered = |floor_change_instructions, starting_floor|
    floor_change_floor_change_instructions_as_integers = floor_change_instructions |> Str.replace_each("(", "1,") |> Str.replace_each(")", "-1,") |> Str.split_on(",") |> List.keep_oks(Str.to_i32)

    resulting_floor = List.walk(
        floor_change_floor_change_instructions_as_integers,
        starting_floor,
        |floor_number, floor_change_instruction|
            Num.add(floor_number, floor_change_instruction),
    )

    Num.to_str(resulting_floor)

expect find_last_floor_entered("(())", 0) == "0"
expect find_last_floor_entered("()()", 0) == "0"
expect find_last_floor_entered("(((", 0) == "3"
expect find_last_floor_entered("(()(()(", 0) == "3"
expect find_last_floor_entered("())", 0) == "-1"
expect find_last_floor_entered("))(", 0) == "-1"
expect find_last_floor_entered(")))", 0) == "-3"
expect find_last_floor_entered(")())())", 0) == "-3"

This one currently doesn't, with the marked error:

determine_moves_until_entering_floor = |floor_change_instructions, starting_floor, target_floor|
    floor_change_floor_change_instructions_as_integers = floor_change_instructions |> Str.replace_each("(", "1,") |> Str.replace_each(")", "-1,") |> Str.split_on(",") |> List.keep_oks(Str.to_i32)

    result = List.walk_with_index_until(
                floor_change_floor_change_instructions_as_integers,
                (starting_floor, 0),
                |state, floor_change_instruction, index| # <-- I am partway through parsing a record pattern, but I got
stuck here: I was expecting to see a closing parenthesis next, so try adding a ) and see if that helps?
                        floor_number = state.0
                        if floor_number == target_floor {
                                Break((floor_number, index))
                        } else {
                                Continue((Num.add(floor_number, floor_change_instruction), index))
                        }
        )

    if result.0 == target_floor {
        Num.to_str((result.1 + 1))
    } else {
        "Floor not reached"
}

expect determine_moves_until_entering_floor(")", 0, -1) == "1"
expect determine_moves_until_entering_floor("()())", 0, -1) == "5"
expect determine_moves_until_entering_floor("(())())", 0, -1) == "7"

view this post on Zulip Anton (Jul 07 2025 at 11:51):

I'll look into this.

view this post on Zulip Anton (Jul 07 2025 at 11:51):

To start, I recommend staying away from { and } for if and function blocks etc in current Roc.

view this post on Zulip Anton (Jul 07 2025 at 12:09):

Didn't really help that the VSCode Plugin seems to break / not show anything when there's a single error and same with the formatting :D

With the new compiler this should be a lot more robust, it's not ready yet though to be clear.

view this post on Zulip Anton (Jul 07 2025 at 12:10):

the VSCode Plugin seems to break

Could it be that the underlined error was very small in that case (see red circle) ?
Screenshot_20250707_140602-1.png

view this post on Zulip Anton (Jul 07 2025 at 12:15):

This works:

determine_moves_until_entering_floor = |floor_change_instructions, starting_floor, target_floor|
    floor_change_floor_change_instructions_as_integers = floor_change_instructions |> Str.replace_each("(", "1,") |> Str.replace_each(")", "-1,") |> Str.split_on(",") |> List.keep_oks(Str.to_i32)

    result = List.walk_with_index_until(
                floor_change_floor_change_instructions_as_integers,
                (starting_floor, 0),
                |state, floor_change_instruction, index|
                        floor_number = state.0
                        if floor_number == target_floor then
                                Break((floor_number, index))
                        else
                                Continue((Num.add(floor_number, floor_change_instruction), index))

        )

    if result.0 == target_floor then
        Num.to_str((result.1 + 1))
    else
        "Floor not reached"


expect determine_moves_until_entering_floor(")", 0, -1) == "1"
expect determine_moves_until_entering_floor("()())", 0, -1) == "5"
expect determine_moves_until_entering_floor("(())())", 0, -1) == "7"

view this post on Zulip Anton (Jul 07 2025 at 12:16):

I got rid of the {}. Note that if requires a then after the condition.

view this post on Zulip Tobias Steckenborn (Jul 07 2025 at 12:42):

That's correct The underlined error was just on the pipe symbol. And indeed it was the then missing in my code (and initially the brackets near the if statements).

So likely something that changed since the version I last used, as I thought I left it in a working state last time. The error was really not that helpful at that position, but given you're currently rewriting the foundations that's likely still a bit out to be realiable :sweat_smile:

Thanks Anton!


Last updated: Jul 26 2025 at 12:14 UTC