Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: FizzBuzz purely in Rust's trait system (github.com/doctorn)
120 points by doctor_n_ on May 24, 2020 | hide | past | favorite | 30 comments


Unusually nursery rhyme-like for code :)

  impl<T: Nat,
    Mod3: Nat,
    Mod5: Nat,
    ShouldFizz: Bool,
    ShouldBuzz: Bool,
    ShouldFizzBuzz: Bool,
    DidBuzz: FizzBuzzType,
    DidFizz: FizzBuzzType,
    DidFizzBuzz: FizzBuzzType>


It's horrible, I love it!

Interesting implementation of `If`, I had no idea the trait system could be... used... to such extent.


A lot of this is fairly standard church encoding.


Not sure why this got downvoted. I'm familiar with Church encoding but not Rust's type system. Armed with that knowledge, I can read the source and deduce what the foreign syntax means. To somebody who knows neither, identifying this pattern can be helpful -- without that, they can read Rust docs and puzzle through the weird construction. With the information, they can read up on Church encoding at an abstract level, and then recognize it in the source -- which can help untangle the Rust syntax.


Oh good. We're reaching C++ levels of template metaprogramming.


C++ allows expressing that more concisely though :p https://twitter.com/Cor3ntin/status/1264600096869691392


That's because it's using constexpr. The equivalent in Rust would be const fn. This is using Rust traits.

The goal isn't to be concise, I think the goal is literally to just do it in the trait system


Makes me think of the time, many, many, many years go, when I was learning IBM 7090 assembly language (my introduction to computers). The macro assembler was powerful enough that I could check for primality at assembly time.


This sounds super awesome! I can't imagine how interesting those times might have been. I started to play around with a 6502 just because there is the possibility to understand the system to some extend. Modern day software engineering is like sitting in the golden cage. Not because the the systems are inaccessible like mobile devices or Apple Computers – you can still get pretty far on Linux systems – but the main reason is that you just can fit all the stuff in your brain. If you try to understand how your Angular/React/whatever project is getting their pixels to the screen all the way down – its just a project for a lifetime and even that is not enough. Understanding modern x86 processors is almost impossible – yeah to some degree enough to understand some basic concepts to not shoot yourself in the foot with how the cache works etc. but getting your hands dirty with an 8-bit processor and reading the datasheet is just something very different.


It's not that bad, check out the Serenity OS project (on Youtube).


It is to be honest. I checked out various OS's and being involved in one of them ( Redox OS ). The problem is that this is "just" the OS part. There are multiple layers above and multiple layers below. Understanding the ins and outs of modern processors (pipelining, branch prediction etc.) motherboards pcie, things like coreboot, modern RAM etc. multiple layers of software abstractions until chrome or firefox have rendered the pixels i command with the javascript engine ... that is just humongous compared to a simple 6502 setup where i am able to really understand every aspect, can replace pieces, build things on top (hard and software) .. making my own RAM ... just for fun. Its a different kind of thing.


While the Serenity OS does not address the layers below, it does address layers above, e.g. the browser.

If you have a blog, I would like to read about your experiments!


You didn't need this, you didn't want this, but here we are.


...and now that you've seen it, you can't unsee it.


At least this kind of thing is genuinely useful as a stress test for the Rust compiler.


Beautiful. With such advances on the frontier of Trait exploitation, soon most of the Rust language will become obsolete and everything will be evaluated on compile-time! It is the ultimate optimization. Just embed the most expected output values in the binary and run time calculation becomes redundant.


On the "clunky syntax" doc comment: a thing typenum does repeatedly is to define generic typedefs that become trait exprs. For example,

  type If<Cond, Then, Else> = <(Then, Else) as If<Cond>>::Output;


I was unaware of typenum until I started showing people this - I'm actually amazed at the level of effort that's gone into it.


Fizz Buzz rules here: https://en.m.wikipedia.org/wiki/Fizz_buzz

Rules for actually using this crate: Don't :-).

That said, there are legitimate reasons to implement things at compile time. It means that libraries can create very efficient code that you don't have to write. But like all of powerful capabilities you should beware of misusing them. Like this :-).


Of course, anything this complicated should probably be a proc macro in Rust.


Your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should.


Wait, there's no loop from 1 to 100. I would not count.


what's Three here?


I was a lil confused too, but that's just an overview of the actual source:

https://github.com/doctorn/trait-eval/blob/master/src/lib.rs



Seems unrelated. Does Java have a compile-time feature that is Turing complete and can be (ab)used to write FizzBuzz? For example, C++ has such a feature: https://gist.github.com/bgaff/2496338 (there's more examples, try searching for "accidentally Turing-complete", there are some really fun solutions.)


As far as i know, No. The compiler stubbornly refuse to inline any method calls.

But it has been proposed in JEP 303 [1]

[1] https://openjdk.java.net/jeps/303


Actually, subtype-checking in Java is Turing-complete. Someone proved this and used the result to build a parser generator for fluent interfaces. [1]

[1] https://arxiv.org/pdf/1605.05274.pdf


They are related in that they both implement FizzBuzz in a way that is highly unlikely to be ever used, nor recommended to be used.


The cases are related because in both implementations it is unlikely that a human computer reader ever halts.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: