Hi fellow Roc'ers,
I've started updating the Exercism track for the new Roc compiler. I have a few exercises passing all the tests, it feels pretty good! :blush: Big shoutout to everyone who maintained this track over the past year, in particular @Anton and @Isaac Van Doren. :thank_you:
I'm currently working on a local branch which I'll push to github.com/exercism/roc very shortly. Once most (or all) exercises are migrated, and once everyone is onboard, we can merge this branch into main and go live.
If anyone wants to help port the exercises, please let me know so we don't work on the same exercises.
Some exercises depend on external libraries:
Most (if not all) other exercises should be fairly easy to migrate today.
amazing, thank you so much for doing this!!! :star_struck:
lmk if you hit any bugs in the new compiler, happy to unblock!
Thanks @Richard Feldman. So far I haven't run into anything serious. Perhaps https://github.com/roc-lang/roc/issues/9574 would be nice to fix, but I can workaround it so no rush at all.
What's the best place to find the list of methods available in the builtins?
In particular, I'm looking for:
Edit
It looks like U64.to_u8 is now U64.to_u8_wrap or U64.to_u8_try. The other functions don't seem to exist yet, but they're not too hard to implement, e.g., compare = |a, b| if a < b { LT } else if a > b { GT } else { EQ }
https://github.com/roc-lang/roc/blob/main/src/build/roc/Builtin.roc
Thanks @Luke Boswell , I'm not sure how I missed this! That said, it might be a good idea to point to this page here: https://www.roc-lang.org/builtins/main/
That page usually list all the functions like real docs :)
It's been broken because of multiple large changes to the codebase, I've been trying to fix it but keep hitting new issues
Awesome, thanks for doing this Aurélien!
Aurélien Geron said:
Perhaps https://github.com/roc-lang/roc/issues/9574 would be nice to fix, but I can workaround it so no rush at all.
fixed in https://github.com/roc-lang/roc/pull/9587
Anton said:
It's been broken because of multiple large changes to the codebase
Me: "We're all trying to find the guy who did this."
![]()
@Anton we should add ci/minici tests that generate the html and do some basic verification of them, like "should be at least ____ entries in the sidebar, each sidebar entry should have at least ____ html elements of this type" (where we fill in those blanks based on our knowledge of the actual number of builtins)
Yeah I already added a test for that :)
I noticed that a few methods have not (yet?) been re-implemented in the new compiler, for example:
I suppose most of these will be under Iter rather than List. I don't mind reimplementing them for Exercism exercise solutions, but it would be good to know which ones are on the roadmap, and which ones have been dropped for good: if a function is on the roadmap, then I might provide it in the exercise stub.
Btw, what's the proper way to convert an iterator to a list? I don't see a to_list() method under Iter, or a from_iter() method under List.
they should be in List too, just didn't get added yet! :smile:
https://roc.zulipchat.com/#narrow/channel/397893-announcements/topic/Iterators/near/599963561
Anton said:
That page usually list all the functions like real docs :)
It's been broken because of multiple large changes to the codebase, I've been trying to fix it but keep hitting new issues
Fixed :)
https://roc-lang.org/builtins/main/
Funny bug here, typing anything into the search seems to lead to scrolling up :sweat_smile:
Hmm, that does not happen in my browser. Can you share your OS and browser?
Mac, Chrome (Version 148.0.7778.168)
![]()
Ok, I am able to reproduce and will make an issue
Richard Feldman said:
lmk if you hit any bugs in the new compiler, happy to unblock!
I've run into a compiler panic while working on porting an exercism solution:
https://github.com/roc-lang/roc/issues/9614
See issue #9614 for more details. :folded_hands:
I've pushed the new branch with 6 ported exercises (accumulate, acronym, affine-cipher, all-your-base, allergies, armstrong-numbers):
https://github.com/exercism/roc/tree/migrate-to-new-roc
If you want to try migrating some exercises:
Then for each exercise (e.g., foo-bar):
Since some builtins are still missing, you'll have to implement them locally. Please mark them with a TODO so we can switch to the actual built-in when available.
I find it quite fun and it's a good way to catch compiler bugs.
10% of all exercises ported (12 / 111). Still a long way to go... :sweat_smile:
FWIW, here's the list of builtins that are needed for the exercises I've worked on so far. For most of them, I wrote a quick & dirty version (and I'll remove them when the builtins are available), but for the math functions, I'm stuck. I'd love to have pow_int, pow, sqrt, cos, sin.
List.map_try: 5 timesList.chunks_of: 3 timesList.intersperse: 3List.join_map: 3List.join: 3Num.pow_int: 3List.reverse: 2 timesList.reverse: 2Str.split_first: 2List.keep_oks: 1 timeList.sort_asc: 1List.sort_desc: 1Num.cos: 1Num.ln: 1Num.pow: 1Num.sin: 1Num.sqrt: 1U64.max_u64: 1Also, an Iter.to_list() function would be very nice (as well as Iter.to_set() and possibly Iter.to_dict()).
The numerics are all implemented in https://github.com/roc-lang/roc/pull/9600 -- its taken me a while to land that PR
That's great, thanks @Luke Boswell
TBH I suspect the failures are unrelated to the changes and more CI things we are ironing out
I looked closer at the numerics CI failure and it looks genuine, so trying to patch that nw
Also Dict is upgraded in https://github.com/roc-lang/roc/pull/9643 -- but also been blocked by CI issues which I suspect are unrelated
I was thinking of tackling List next but I see @Jared Ramirez has been doing a lot of work in that space so I was going to hold off a while
im almost done implemented range syntax desugaring to itrs! hoping to land asap
38 exercises done with all tests passing.
+4 done but the compiler crashes.
69 exercises to go (including 8 which rely on external libraries).
74 exercises done, 28 to go.
91 exercises done, 19 to go.
Getting close! However, the last ones are the longest, and they also include the 8 exercises that depend on external libraries.
You can check out the updated branch here:
https://github.com/exercism/roc/tree/migrate-to-new-roc
I'm not 100% confident about the right interface for some exercises, in particular error-handling and the data structure exercises, includingcomplex-numbers, rational-numbers, list-ops, custom-set, simple-linked-list, circular-buffer, and binary-search-tree.
If you want to check out some of these and tell me what you think, here's how things are organized: let's take rational-numbers, for example. Everything is located under the exercises/practice/rational-numbers directory:
.docs subdirectory contains the instructions for the users. Usually these are generic (i.e., the same for all programming languages), but sometimes there are some Roc-specific instructions in .docs/instructions.append.md so watch out for these.RationalNumbers.roc type module (which is just a stub).rational-numbers-test.roc and they will see the error messages, if any. This file is usually generated automatically using the .meta/template.j2 template, based on the standard list of tests for each exercise..meta/Example.roc, but the users never see it: it is only there to run tests when updating the Roc track, so it's not as important as the stub or the tests.Can you make a WIP PR using your branch @Aurélien Geron? That makes it easy to review and comment on things.
Good point, I'll do that.
Anton said:
Can you make a WIP PR using your branch Aurélien Geron? That makes it easy to review and comment on things.
Here it is: https://github.com/exercism/roc/pull/198
I have reviewed up to the grep exercise, tomorrow I will probably just take a look at your list from earlier: error-handlingand the data structure exercises, includingcomplex-numbers, rational-numbers, list-ops, custom-set, simple-linked-list, circular-buffer, and binary-search-tree.
It's a lot of code to review and it must have been a ton of work to upgrade all those exercises, thank you so much @Aurélien Geron :heart:
Thanks a lot @Anton! I'm going through your comments now.
We have a performance issue on some exercises, they take over two minutes to run (with the previous compiler they took a few seconds):
The alphametics exercise takes over 10 seconds, which is a bit too long too, but below exercism.org's threshold (25 seconds, IIRC).
Is this with --opt=dev --opt=interpreter or --opt=speed etc? (it may be backend specific)
Are you building these before running them roc build app.roc && ./app, or running directly roc app.roc? (it may be specific to our shims or shared memory)
It's just with zig build build-release.
If it's slow on everything than it is probably bugs in the pipeline.
What command do you use to run the apps?
I run ./bin/verify-exercise nth-prime but under the hood it runs roc test nth-prime-test.roc
My immediate hunch is that it might be something like the expects run at comptime using the interpreter (which is pretty slow currently)
I don't have capacity to dig into this in much detail today. But I assume we would have a lot of room to improve on this.
Ah, interesting. I'll try running these exercises using roc rather than roc test
So running directly with roc app.roc should use the dev backend by default now, and building roc build app.roc should use the llvm backend by default
Ah, ok, so the fastest would be roc build app.roc then ./app?
yeah fastest run time, slowest compile time
Interesting: when I move the tests to the main! function, and I build nth-prime using roc build nth-prime-test.roc, then it takes too long time to build (at least 3 minutes, I interrupted it). But if I tweak the main! function to ensure that the function args depend on the main! arguments, so the compiler can't try to run the tests at compile time, then compilation takes under a second, and running the program also runs under a second. So at first glance it seems that the performance issue is when roc tries to run the function at compile time.
Yeah that sounds about right
Should I open an issue?
I think that would be helpful. I think @Richard Feldman has plans for comptime eval to be ran by the dev backends ... I'm not sure what the status of that is.
Oh wait, I just tweaked something in the NthPrime.roc type module, and now roc test runs in 9ms!
whoa, what was the tweak? haha
oh I bet it was an infinite loop somewhere
(possibly in our compiler)
So the code was like this:
NthPrime :: {}.{
prime : U64 -> Try(U64, [NoPrime0])
prime = |number| {
if number == 0 {
Err(NoPrime0)
} else if number == 1 {
Ok(2)
} else if number == 2 {
Ok(3)
} else {
find_prime = |primes, index, number2| {
if primes.len() == number2 {
primes
} else {
next_index = index + 2
new_primes = {
if primes.any(|p| next_index % p == 0) {
primes
} else {
primes.append(next_index)
}
}
find_prime(new_primes, next_index, number2)
}
}
find_prime([2, 3, 5], 5, number)
.last()
.map_err(
|_| {
crash "Unreachable: list cannot be empty"
},
)
}
}
}
I had to use number2 because of https://github.com/roc-lang/roc/issues/9690 but since you fixed this issue (thank you!) I removed number2, and it fixes the performance issue.
I don't think it's an infinite loop, because the tests would pass; but they would take over 2 minutes.
For completeness, here's the new code that allows the tests to pass in 9ms:
NthPrime :: {}.{
prime : U64 -> Try(U64, [NoPrime0])
prime = |number| {
if number == 0 {
Err(NoPrime0)
} else if number == 1 {
Ok(2)
} else if number == 2 {
Ok(3)
} else {
find_prime = |primes, index| {
if primes.len() == number {
primes
} else {
next_index = index + 2
new_primes = {
if primes.any(|p| next_index % p == 0) {
primes
} else {
primes.append(next_index)
}
}
find_prime(new_primes, next_index)
}
}
find_prime([2, 3, 5], 5)
.last()
.map_err(
|_| {
crash "Unreachable: list cannot be empty"
},
)
}
}
}
fascinating! yeah if you can include all of that in the issue, would be helpful in figuring out what went wrong there :smiley:
Sounds good. :+1:
@Richard Feldman is roc test dev backend or interpreter? (by default)
should be dev backend but I forget if I switched it over yet :sweat_smile:
in theory only compile-time evaluation of constants should still be using interpreter
Yeah I remember making the PR to enable the different backends but unsure which it ran with.
Oops, sorry, I got mixed up with the multiple versions I tried locally. It's actually the reverse: the version WITH number2 runs fast, but the version without it runs slowly.
Oh actually... the 9ms might have been an illusion due to caching, duh. I'm investigating.
Yeah, sadly the 9ms was probably a caching thing, I couldn't reproduce it without caching.
I opened https://github.com/roc-lang/roc/issues/9747
103 exercises migrated, 1643/1644 tests pass! I opened an issue for that last failing test.
The 7 remaining exercises are the ones that depend on external libraries.
I'm focusing on migrating the roc-test-runner now.
I've migrated the roc-test-runner. Here's the draft PR for review:
https://github.com/exercism/roc-test-runner/pull/42
Thanks @Aurélien Geron, I will check out the PR
Since the roc-parser library was migrated, I could update the sgf-parsing exercise: all tests pass. :grinning:
I also updated the code to use the new sqrt, cos, sin, e, pi, and compare functions, thanks @Luke Boswell .
Still missing a few builtins:
List.chunks_ofList.intersperseList.join_mapList.joinList.keep_oksList.map_tryList.sort_ascList.sort_descNum.is_approx_eqNum.logNum.pow_intNum.roundNum.sub_saturatedStr.split_firstAlso, perhaps add:
exp = |x| F64.e.pow(x)
Using the draft PR #31, I managed to migrate the three exercises that depend on the unicode library: anagram, micro-blog, and reverse-string. All tests pass. :tada:
108 exercises migrated, only 2 to go! :tada: These two exercises depend on the isodate library, which I'm working on migrating (but I'm travelling, so it might take a couple of weeks).
Almost all the tests pass, with just two exceptions:
binary-search-tree exercise. I opened issue #10057. All the tests used to pass.rest-api exercise fails because of a comparison bug. I opened issue #10049.We're soooo close! :smiley:
Edit: I forgot to mention that thanks to Json.parse and Json.to_str, the only exercise that depended on the json library (i.e., rest-api) no longer needs it. Pretty cool. :+1:
Last updated: Jul 23 2026 at 13:15 UTC