I was just glossing over some examples here, and I couldn't help but notice, how 'boring' the fizz-buzz example is. The most elegant/expressive/concise implementation I have ever seen is the one below. Does anyone know if such level of elegance and purity can be achieved with Roc? I do understand that Roc doesn't have lazy-sequences, but at the same time I don't mean translate this code line by line - perhaps the core idea can be translated in Roc w/o laziness...
Screenshot-from-2024-06-02-21-28-04.png
Personally, I think I would just go with something simple:
fizzbuzz = \i ->
when (i % 3, i % 5) is
(0, 0) -> "FizzBuzz"
(0, _) -> "Fizz"
(_, 0) -> "Buzz"
_ -> Num.toStr i
ok that is nicer, but you're still doing two modulo operations, 4 ifs, and writing "FizzBuzz"
by hand
A more direct translation would be this:
a = ["Fizz", "", ""]
b = ["Buzz", "", "", "", ""]
getWrap = \list, i ->
when List.get list (i % List.len list) is
Ok v -> v
Err _ -> crash "invalid"
fizzbuzz = \i ->
when Str.concat (getWrap a i) (getWrap b i) is
"" -> Num.toStr i
x -> x
ok now we're talking
wow this is great
oh I see - you've basically made up this 'gap-cycle' yourself
i mean there may be a better way to do this, but the core function certainly reads great
thanks again!
but wait - getWrap can crash the program?
Only is the list is size 0
So in this case it is impossible
shouldn't the Err case return the empty string?
oooo i see
right right
so your second version is essentially branch-less - the only conditional is comparing the empty String with the result of Str.concat
, which should be super cheap.
and List.len
I assume is a constant-time operation
Yep
Last updated: Jul 05 2025 at 12:14 UTC