Live data from Hacker News

Why your first Rust FizzBuzz implementation may not work

chrismorgan.info

21–30 of 139 posts

Re: Why your first Rust FizzBuzz implementation may not work

#21
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 contemplated using `match` in the article, but decided that there was enough to think about and that it was long enough already. Thanks for pointing it out, though—it certainly is a great thing!

Re: Why your first Rust FizzBuzz implementation may not work

#22
post #14
post #11

What's up with the "alternative" form of Python? What about braces, semicolons, and an explicit main() function makes that version worth showing?

Well, "from __future__ import braces" is a joke, so applying the transitive property of jokes, I assume this alternative version is a joke as well.

Indeed it is. And people should certainly try executing `from __future__ import braces` if they’re not familiar with what it is.

As for the main function and `if __name__ == '__main__': main()`, that part is actually generally recommended.

Re: Why your first Rust FizzBuzz implementation may not work

#23

The feature list in rust really does have my eye. The biggest one in particular was type inference . The reason type inference was such a big one was because if you use it right, annoying situations like "Two types of strings? What is this?" go the hell away. You have three types, static built in and binary strings, and a third that only makes the gaurentee that the datatype can do all the things a string aught to be…

Rust has type inference similar to Haskell: type information can flow "backwards". It is very different to Go and C++ where types of locals are 'inferred' from their initialiser, and nothing else.

E.g.

  fn main() {
      let mut v;

      if true {
          v = vec![];
          v.push("foo");
      }
  }
is a valid Rust program: the compiler can infer that `v` must have type `Vec` based on how it is used. I don't think it's possible to syntactically write a Go program at all similar to this (a variable has to be either initialised or have a type), and the C++ equivalent (using `auto v;`) is rejected, as `auto` variables need an initialiser.

Re: Why your first Rust FizzBuzz implementation may not work

#24

The feature list in rust really does have my eye. The biggest one in particular was type inference . The reason type inference was such a big one was because if you use it right, annoying situations like "Two types of strings? What is this?" go the hell away. You have three types, static built in and binary strings, and a third that only makes the gaurentee that the datatype can do all the things a string aught to be…

Type inference doesn't exactly paper over the differences between types automatically. It just infers types, and doesn't complain as long as all the types line up.

Consider doing something similar in Haskell, setting a variable to either be a string or Text:

    GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
    Prelude> import qualified Data.Text as T
    Prelude T> let x = (if True then "foo" else T.empty)

    :3:32:
        Couldn't match expected type `[Char]' with actual type `T.Text'
        In the expression: T.empty
        In the expression: (if True then "foo" else T.empty)
        In an equation for `x': x = (if True then "foo" else T.empty)
Sure, Haskell can sometimes auto-infer very complex types, and has more extensive type inference than Rust does. But it's not magic, and will not do everything for you.

What you're asking for is not type inference, but something else. Perhaps what you really want is weak typing (automatic type conversions), or message sending (can not statically dispatch).

Re: Why your first Rust FizzBuzz implementation may not work

#25
post #12

Earlier quoted context omitted.

I disagree. I think code comparisons should be done using idiomatic code. I personally would not consider chaining `if` expressions like you've done here idiomatic Python.

and yet people write: let result = if i % 15 == 0 { "FizzBuzz" } else if i % 5 == 0 { "Buzz" } else if i % 3 == 0 { "Fizz" } else { i }; in rust? either this is good, readable code or this is poorly written, unintelligible code. you cannot make the argument that sometimes it is readable and sometimes not based on the presence of braces.

Using `if .. else if .. else` in Rust as an expression is absolutely idiomatic.

Re: Why your first Rust FizzBuzz implementation may not work

#26
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 all intuitive. For example, as an outsider, I'd expect it to be (0, 1) instead of (0, 0) since it's matching both the 0th and 1st patterns. Whereas (0, _) would be "0th pattern but not the 1st," or something, even though that really wouldn't make much sense because "0" would refer to which pattern it's matching, rather than the position of the argument determining which pattern it's matching. Etc.

If Rust is the most robust way to solve a problem, it should naturally catch on. It seems pretty promising in that regard.

EDIT: As a counter to my comment, my argument would be equally applicable to Lisp, and Lisp is beautiful. So my argument is probably mistaken.

Maybe someone has to learn a language before judging whether it's beautiful.

Re: Why your first Rust FizzBuzz implementation may not work

#27
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…

It’s whether (i % 3, i % 5) is equal to (0, 0) et al., where _ means “any value”.

Re: Why your first Rust FizzBuzz implementation may not work

#28
For what it's worth, String in Rust is similar to StringBuffer in other languages. You can append to a String; you can't append to a slice, which always represents a fixed view.

A slice has storage that is borrowed from somewhere else, but it itself does not have its own storage.

When you type `"foo"`, you are creating "static" storage (in the binary) and the slice is borrowed from that fixed-position location in memory.

Mostly, your functions produce Strings and consume slices.

Re: Why your first Rust FizzBuzz implementation may not work

#29

Earlier quoted context omitted.

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…

It’s whether (i % 3, i % 5) is equal to (0, 0) et al., where _ means “any value”.

That's a very useful feature. Maybe I'll go ahead and learn Rust now. If it has a features like pattern matching, which seems about ten times more useful than the classic switch statement, then it probably has a lot of other insights worth learning.

If you were to start a hypothetical project written in Rust, what would it be? I'm looking for something to cut my teeth on.

Re: Why your first Rust FizzBuzz implementation may not work

#30
post #28

For what it's worth, String in Rust is similar to StringBuffer in other languages. You can append to a String; you can't append to a slice, which always represents a fixed view. A slice has storage that is borrowed from somewhere else, but it itself does not have its own storage. When you type `"foo"`, you are creating "static" storage (in the binary) and the slice is borrowed from that fixed-position location in mem…

And that indeed is the real distinction between what Rust has and what other languages tend to have—the fact that &str doesn’t have its own storage. The equivalent to string types in other languages would be more like SendStr.

That functions produce Strings and consume slices is a good way of expressing it.

Post reply on HN