Live data from Hacker News

Why your first Rust FizzBuzz implementation may not work

chrismorgan.info

121–130 of 139 posts

Re: Why your first Rust FizzBuzz implementation may not work

#121
post #20

Putting the String issue aside, I just wanted to show the beauty of pattern matching. for i in range(1i, 101) { match (i % 3, i % 5) { (0, 0) => println!("Fizzbuzz"), (0, _) => println!("Fizz"), (_, 0) => println!("Buzz"), _ => println!("{}", i), } } -- edited: removed `.to_string()`, thanks chrismorgan

I fail to see how a simple switch statement doesn't read just as easily. I mean, sure I have to know the mod 15 trick, but... not exactly hard.

    function fizzBuzz(i) { 
      switch(i % 15) { 
        case 0: return "fizbuzz";
        case 5: 
        case 10: return "buzz";
        case 3:
        case 6:
        case 9:
        case 12: return "fizz";
        default: return i.toString();
      }
    }
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].map(fizzBuzz)

Re: Why your first Rust FizzBuzz implementation may not work

#123
post #121
post #20

Putting the String issue aside, I just wanted to show the beauty of pattern matching. for i in range(1i, 101) { match (i % 3, i % 5) { (0, 0) => println!("Fizzbuzz"), (0, _) => println!("Fizz"), (_, 0) => println!("Buzz"), _ => println!("{}", i), } } -- edited: removed `.to_string()`, thanks chrismorgan

I fail to see how a simple switch statement doesn't read just as easily. I mean, sure I have to know the mod 15 trick, but... not exactly hard. function fizzBuzz(i) { switch(i % 15) { case 0: return "fizbuzz"; case 5: case 10: return "buzz"; case 3: case 6: case 9: case 12: return "fizz"; default: return i.toString(); } } [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].map(fizzBuzz)

Even that is better in Rust (using the enum from the end):

    match i % 15 {
        0 => FizzBuzz,
        5 | 10 => Buzz,
        3 | 6 | 9 | 12 => Fizz,
        _ => Number(i),
    }

Re: Why your first Rust FizzBuzz implementation may not work

#124

Earlier quoted context omitted.

Python doesn't have pattern matching but the code is basically the same. I guess better cases for showing off the feature are ones where the patterns aren't just True/False tuples. for i in range (1, 101): fbsign = (i % 3 == 0, i % 5 == 0) if fbsign == (1, 1): print("Fizzbuzz") elif fbsign == (1, 0): print("Fizz") elif fbsign == (0, 1): print("Buzz") else: print(i)

Some people are sayint this is extremely non idiomatic python. I think most of the problem is not following the style guides. Here's a pep8 compliant solution that is a bit more idomatic, and almost as compact. In Python, the way to do pattern matching is with dictionaries of functions. fizz_buzz = {(True, True): lambda x: "Fizzbuzz", (True, False): lambda x: "Fizz", (False, True): lambda x: "Buzz", (False, False): l…

That's not genuinely pattern matching, however. It only works for patterns without member binding.

Re: Why your first Rust FizzBuzz implementation may not work

#125
post #121

Earlier quoted context omitted.

I fail to see how a simple switch statement doesn't read just as easily. I mean, sure I have to know the mod 15 trick, but... not exactly hard. function fizzBuzz(i) { switch(i % 15) { case 0: return "fizbuzz"; case 5: case 10: return "buzz"; case 3: case 6: case 9: case 12: return "fizz"; default: return i.toString(); } } [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].map(fizzBuzz)

Even that is better in Rust (using the enum from the end): match i % 15 { 0 => FizzBuzz, 5 | 10 => Buzz, 3 | 6 | 9 | 12 => Fizz, _ => Number(i), }

I actually agree it is better. But... my point was that the switch statement was already pretty readable. If there are gains, they feel pretty small in these examples.

And to be clear, I like pattern matching. A lot. I just don't feel this really shows it off that well.

Re: Why your first Rust FizzBuzz implementation may not work

#126

I've always liked this c++ implementation of FizzBuzz, its not the most clear or logical but its short; const char* outs[] = { "%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n" }; for (int i = 1; i

Is that allowed by the standard? (Passing a parameter to `printf` but not referencing it, in the non-"%d\n" case?)

C11 §7.21.6.1

  If the format is exhausted while arguments remain, the excess
  arguments are evaluated (as always) but are otherwise ignored.
but that's just a consequence of stdarg, which does not require all supplied arguments to be consumed.

Re: Why your first Rust FizzBuzz implementation may not work

#127
post #125

Earlier quoted context omitted.

Even that is better in Rust (using the enum from the end): match i % 15 { 0 => FizzBuzz, 5 | 10 => Buzz, 3 | 6 | 9 | 12 => Fizz, _ => Number(i), }

I actually agree it is better. But... my point was that the switch statement was already pretty readable. If there are gains, they feel pretty small in these examples. And to be clear, I like pattern matching. A lot. I just don't feel this really shows it off that well.

What do you expect; it's FizzBuzz.

Re: Why your first Rust FizzBuzz implementation may not work

#128
post #125

Earlier quoted context omitted.

Even that is better in Rust (using the enum from the end): match i % 15 { 0 => FizzBuzz, 5 | 10 => Buzz, 3 | 6 | 9 | 12 => Fizz, _ => Number(i), }

I actually agree it is better. But... my point was that the switch statement was already pretty readable. If there are gains, they feel pretty small in these examples. And to be clear, I like pattern matching. A lot. I just don't feel this really shows it off that well.

Only because you're expecting the cases to fall through, you're being blinded by your own expectation.

Your code is considered bad practice in many languages.

Re: Why your first Rust FizzBuzz implementation may not work

#129
post #20

Putting the String issue aside, I just wanted to show the beauty of pattern matching. for i in range(1i, 101) { match (i % 3, i % 5) { (0, 0) => println!("Fizzbuzz"), (0, _) => println!("Fizz"), (_, 0) => println!("Buzz"), _ => println!("{}", i), } } -- edited: removed `.to_string()`, thanks chrismorgan

I guess beauty is in the eye of the programmer. I'd choose Python's or Ruby's FizzBuzz. It's beautiful that everyone can immediately understand those. This one, not so much. As a little experiment, I've deliberately avoided learning Rust to see if I can understand its idioms without reading any docs. I can sort of guess at what's going on here by reverse engineering what should happen with FizzBuzz, but it's not at a…

> As a little experiment, I've deliberately avoided learning Rust to see if I can understand its idioms without reading any docs.

As an experiment of what? Whether rust code makes somewhat sense to you depends to an extent on what languages you already know (I guess ML languages would help). Same as with Ruby and Python.

Re: Why your first Rust FizzBuzz implementation may not work

#130
post #34

Earlier quoted context omitted.

Here's the same approach in F# without the different types of String; therefore, easier to get more functional. let fizzbuzz num = match num % 3, num % 5 with | 0,0 -> "FizzBuzz" | 0,_ -> "Fizz" | _,0 -> "Buzz" | _,_ -> num.ToString() [1..100] |> List.map fizzbuzz |> List.iter (fun (s:string) -> printfn "%s" s)

Haskell - fizzbuzz x = case (x `mod` 3, x `mod` 5) of (0, 0) -> "FizzBuzz" (0, _) -> "Fizz" (_, 0) -> "Buzz" _ -> show i mapM_ (putStrLn . fizzbuzz) [1..100]

Pattern matching is one of the ways to get "two-mod" code where the modulus operator is used two times. For example, string concatenation and assignment operators do the same in this Python code:

    for i in range(1, 101):
        x = ""
        if i % 3 == 0:
            x += "Fizz"
        if i % 5 == 0:
            x += "Buzz"
        if x == "":
            x += str(i)
        print(x)
If anybody is randomly curious it can be fun to solve FizzBuzz in Haskell the same way that this Python code does it, but (to be more idiomatically Haskell) storing the FizzBuzz success in a Maybe (or some other variable). If you define the appropriate `~>`, and higher-precedence `|~`, and higher-precedence `|~~>`, you can write the above function as:

    fizzbuzz x = 
        mod x 3 == 0    ~> "Fizz" 
        |~ mod x 5 == 0 ~> "Buzz" 
        |~~> show x 
It's interesting because it's sort of a "follow-through guards" situation; the (|~) operator can at least be turned into a type signature of (Monoid m) => Maybe m -> Maybe m -> Maybe m.
Post reply on HN