Stream: advent of code

Topic: Daily solving of AoC on Twitch


view this post on Zulip Scally (Dec 11 2024 at 02:21):

Hi, I'm currently streaming my daily solves of AoC on Twitch.

Since I'm new to functional programming and Roc I'd love if some more experienced people would join my chat and provide feedback and improvements on the frequently horrible code I write :D

Beginners are always welcome too obviously.

You can find it on https://twitch.tv/ScallyGamesDev

view this post on Zulip Brendan Hansknecht (Dec 11 2024 at 02:49):

What time do you normally stream?

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:03):

Woah, there's ads on Twitch :grimacing: -- I hope they don't interrupt streams

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:06):

Just listening to Day 10 now... :smiley:

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:19):

@Scally mind if I drop some ideas for you in here?

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:20):

Checkout List.keepOks -- I like to use that sometimes for AoC for quick and dirty parsing the lines where I have a Result

view this post on Zulip Scally (Dec 11 2024 at 03:49):

Brendan Hansknecht said:

What time do you normally stream?

Well... :sweat_smile: that unfortunately varies widely.
Usually around afternoon/evening CET but also sometimes late night or early morning xD
I'd say probably easiest to follow to get notified when I go live :thinking:

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:50):

Alright, I'll give you a sub

view this post on Zulip Scally (Dec 11 2024 at 03:50):

They sadly do @Luke Boswell :| Also you sadly can't fully turn them off as a streamer. I'd honestly recommend using adblocks

view this post on Zulip Scally (Dec 11 2024 at 03:51):

Follow is good enough and free, sub is appreciated nontheless :D
Also thanks for checking out the VOD

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:52):

Apparently I'm a Twitch noob... I'm the guy that catches streams people have uploaded to YT

view this post on Zulip Scally (Dec 11 2024 at 03:53):

Luke Boswell said:

Scally mind if I drop some ideas for you in here?

Sure, I'd love that
I've used List.keepOks a bunch already but yes, managing errors and results is one of my biggest troubles still.
Can you tell me why List.keeppOks takes a function as argument instead of just working on a list of results? It seems somewhat annoying. Or is there some better way to include it in a pipeline than going

somethingThatGeneratesListOfResults |> List.keepOks \x -> x

view this post on Zulip Scally (Dec 11 2024 at 03:54):

Yeah, youtube subscribes are twitch follows, twitch subscribes are paid support that unlocks emotes and some other stuff.
To me the youtube subscribe term always felt weird because it seemed to me like it was paid.

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:55):

Not to confuse things further, but I pay for YT so I don't have ads

view this post on Zulip Scally (Dec 11 2024 at 03:56):

Also something that's been repeatedly annoying to me is Results after I know that it won't fail.
Something like

# already did bound check
List.get list 0

What I usually do is pipe it into Result.withDefault 0 or something alike, knowing it will never happen, but it always feels really bad

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:57):

I sometimes throw a quick and dirty one of these in and use that for AoC

unwrap : Result ok err -> ok
unwrap = \result ->
    when result is
        Ok value -> value
        Err _ -> crash "expected Ok"

view this post on Zulip Scally (Dec 11 2024 at 03:58):

Luke Boswell said:

Just listening to Day 10 now... :smiley:

Btw, AoC 10 has probably been one of my better days :laughter_tears:

Some days were that terrible that I did a second stream for redemption trying to improve on my solution xD

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:58):

I think that is fine for these kind of programs where we are just slapping code together and not too concerned about errors

view this post on Zulip Scally (Dec 11 2024 at 03:58):

Okay, I was wondering because some other languages have unwrap (I think I know it from Rust) but Roc doesn't

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:58):

As I've learnt more though, I've found my need for that has dropped off dramatically though, so it's definitely something I've gotten more comfortable with handling the errors and passing them up through the program

view this post on Zulip Luke Boswell (Dec 11 2024 at 03:59):

Using ? makes like much easier too

view this post on Zulip Scally (Dec 11 2024 at 04:00):

I was assuming that it's something that would go away as I got better but so far I haven't found any great solutions.
My assumption is that Result.try or the new try keyword will help but I haven't quite figured out how to properly use that.

view this post on Zulip Scally (Dec 11 2024 at 04:00):

Usually any attempts to use try results in compiler errors because of incorrect arguments to something xD

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:00):

part1 : Str -> Result Str _
part1 = \input ->

    tests : List Test
    tests = parseStr? (sepBy parse_test (codeunit '\n')) (Str.trim input)

    ...

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:01):

The key thing in this example is that I use a _ to infer the error type

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:01):

So I don't care about the errors from my parseStr function.. that just gets passed up the chain

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:02):

So try and ? are implemented identically under the hood now. In the long term I suspect ? will fit nicer with the parens and commas design that's been kicking around. But for now we have both.

view this post on Zulip Scally (Dec 11 2024 at 04:06):

Interesting, I'll have to look into the Str -> Result Str _ tomorrow, bubbling up errors is kind of what I wanted, just never seemed to get it to work.
Initially it was also really confusing because iirc some APIs actually throw errors instead of returning results and those errors just stop execution of the function and in the end crash the program.
In many cases I wished I'd just get a crash instead of a Result. Is there some way to convert an Err to a crash? I assume the custom unwrap function you've posted above?

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:06):

I assume the custom unwrap function you've posted above?

Yes, this is the only way

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:07):

some APIs actually throw errors instead of returning results

This should only be for things that cannot be handled in any sensible way but crashing

view this post on Zulip Scally (Dec 11 2024 at 04:08):

Ah, I think it was mostly for Tasks

view this post on Zulip Scally (Dec 11 2024 at 04:09):

I remember some videos / talks by Richard where he showed off some basic programs and it was basically only crashes, no working with results there.

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:09):

I'm currently listening to you explaining why AoC isn't well suited for FP :smiley:

view this post on Zulip Scally (Dec 11 2024 at 04:10):

There was some really neat Haskell implementation for today's task by someone in my chat

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:10):

https://github.com/Andriamanitra/adventofcode2024/blob/main/day10/solution.hs

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:10):

Lol, looking at it rn

view this post on Zulip Scally (Dec 11 2024 at 04:11):

Jup, that's the one

view this post on Zulip Scally (Dec 11 2024 at 04:11):

Today and the one with the bridge and doing math operations on a list of operands was really nice with FP

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:13):

My Roc tends to be really verbose... but I don't mind it like that.

I tend to write smaller parts and then use expects to test my assumptions at each point as I go.

Others seem to be able to keep a whole algorithm in their head and write something correct using much less code than me.

view this post on Zulip Scally (Dec 11 2024 at 04:15):

I just recently started breaking things up more and more since doing long function chain would result in the editor underlining like 12 lines of code saying there was something wrong with some type at some point in those lines :sweat_smile:

view this post on Zulip Scally (Dec 11 2024 at 04:16):

Also I had some really bad issues with some stupid single value or operation incorrectly inferring some type which then messed up some type signature way up the chain

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:17):

I really like working with the compiler and using type annotations to help me "think" about the algorithm. Like I can "pin" the type at a point and get instant feedback if the compiler agrees with me or not.

view this post on Zulip Scally (Dec 11 2024 at 04:17):

Like somewhere in the function chain some U64 + Num (but actually I64 or similar) operation which then suddenly changes the entire type of the Num to U64 which then bubbles up instead of it telling me I couldn't do addition between unsigned and signed int.

view this post on Zulip Scally (Dec 11 2024 at 04:18):

Creating smaller functions and adding explicit type annotations really helped on that

view this post on Zulip Scally (Dec 11 2024 at 04:18):

Yeah, I think I talked about it on today's stream that I really started to like starting to write a function in terms of it's signature

view this post on Zulip Brendan Hansknecht (Dec 11 2024 at 04:21):

Yeah, I often start with types for anything vaguely complex

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:22):

Here's an example... I'm even doing it in the middle of a function.

part1 : Str -> Result Str _
part1 = \input ->

    tests : List Test
    tests = parseStr? (sepBy parse_test (codeunit '\n')) (Str.trim input)

    valid_tests : List Test
    valid_tests =
        List.keepIf tests \test ->
            k = 2 # Add, Mul
            find_first_valid_ast test k |> Result.isOk

    valid_tests
    |> List.map .test_value
    |> List.sum
    |> Num.toStr
    |> Ok

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:23):

Usually I'm writing that as I think through the algorithm, so even though it's more verbose it somehow saves me wall time, because I get to a correct solution faster.

view this post on Zulip Scally (Dec 11 2024 at 04:23):

Yeah, I've started doing some of that

view this post on Zulip Scally (Dec 11 2024 at 04:24):

Btw, do you have any recommendations on a function lacking a return or having 2 returned values breaking all of intellisense and type checking? :sweat_smile:

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:25):

I'm not sure I've seen this issue before

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:26):

Oh, like if it can't parse the file it prevents type checking?

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:26):

I think @Joshua Warner or @Sam Mohr were working on something for a more tolerant parser

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:28):

Actually... that might be what is going on with this issue https://github.com/roc-lang/roc/issues/7332 I just reported from your comments on stream. I asked Josh and he said it looks like it may be language server related

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:29):

Yeah, running roc check gives use the expected error report. So this is a language server thing.

view this post on Zulip Scally (Dec 11 2024 at 04:29):

Like something like

doSomething = \a ->
    test = getSomething
    # currently still working on this function

part1 -> \input
# ....

or

doSomething = \a ->
    getSomething
    a == 1

part1 -> \input
# ....

usually resulted in a general parser error and breaking all editor integration.

I think it's been more of an issue with Zed than in VSCode and especially annoying because the error message says something like

Error parsing

somewhere around here
========
            doSomething = \a ->
[120]         test = getSomething
                               ^
========

so it seems to know the line number but it only shows the error on line 1 on the app keyword (I guess character 1 of the file).

view this post on Zulip Scally (Dec 11 2024 at 04:30):

Luke Boswell said:

I think Joshua Warner or Sam Mohr were working on something for a more tolerant parser

yeah, exactly that.

I think earlier I saw something on a thread here about having to reload the Zed editor because it was breaking all the time.

view this post on Zulip Scally (Dec 11 2024 at 04:31):

#advent of code > 2024 Day 1 @ 💬

view this post on Zulip Luke Boswell (Dec 11 2024 at 04:36):

Another thing I've found that saves a lot of pain, is actually parsing the input. So instead of leaving the "heights" as U8, parsing that into Heights: [L1, L2, L3, ..] for example. On the days when I don't use roc-parser I tend to find at lesat two or three bugs where I simply just assume something obvious like forgetting that '9' and 9 are different numbers :sweat_smile:

view this post on Zulip Scally (Dec 11 2024 at 04:40):

Hm... so parsing the integers into Tags? I've done that on the defragmentation task and it was quite nice (apart from sometimes being confused with the syntax of opaque types)

view this post on Zulip Brendan Hansknecht (Dec 11 2024 at 05:54):

Clip on intellisense issues for reference: https://www.twitch.tv/scallygamesdev/clip/ComfortableTenuousSrirachaPJSalt-id4WvH-OQXEwCGcU

cc @Sam Mohr and @Joshua Warner who work on the parser.

view this post on Zulip Luke Boswell (Dec 11 2024 at 05:55):

I think it's a language server thing. @Eli Dowling said he'll have a look at it and scope (suss) it out.

view this post on Zulip Brendan Hansknecht (Dec 11 2024 at 05:58):

Ah, sorry for wrong pings then.

view this post on Zulip Luke Boswell (Dec 11 2024 at 06:00):

Alg, I just wanted to let Sam and Josh know I'd had a quick chat to Eli

view this post on Zulip Anton (Dec 11 2024 at 10:02):

so it seems to know the line number but it only shows the error on line 1 on the app keyword (I guess character 1 of the file).

Can we do a quick change for this that underlines the entire file? I usually never notice the top error for a while and I continue thinking my code is all correct. It's easier to fix errors immediately.

view this post on Zulip Eli Dowling (Dec 11 2024 at 11:08):

I will try to fix it today @Anton if I can't get it solved I'll make a pr changing the default scope :)

view this post on Zulip Anthony Bullard (Dec 11 2024 at 16:54):

Language server reports a lot of weird errors I don't see with roc check, and it will stick around at the top of the file forever until you restart the LSP.

view this post on Zulip Anton (Dec 11 2024 at 16:56):

Language server reports a lot of weird errors I don't see with roc check

That is strange, I don't think I've ever had that, do you have an example?

view this post on Zulip Eli Dowling (Dec 11 2024 at 17:05):

I've definitely had the lsp get into a nasty not dead not alive state before. Got a deadlock in there somewhere I guess. I'm not sure if we have a way of timing out when the compiler hangs. Which it does fairly often with recursive code.

view this post on Zulip Anthony Bullard (Dec 11 2024 at 18:11):

Hanging -> in a when will do it for me pretty reliably

view this post on Zulip Anthony Bullard (Dec 11 2024 at 18:12):

But I have a lot more feedback on language server when I have time to write it down


Last updated: Jul 06 2025 at 12:14 UTC