Live data from Hacker News

Why your first Rust FizzBuzz implementation may not work

chrismorgan.info

61–70 of 139 posts

Re: Why your first Rust FizzBuzz implementation may not work

#61
post #59

Earlier quoted context omitted.

[deleted]

I deliberately didn’t go about omitting the number 15 or the string FizzBuzz, because that would have distracted from the key points I was making about Rust. It is not possible to make it as efficient under those constraints—you end up needing either more than one print call, or to use an owned string, where I was able to end up with a solution that didn’t require any heap memory at all.

yeah. I'm being too nitpicky. I guess part of the "beauty" is that 3*5==15 but I realized that you'd need more complexity after hitting the reply button.

Re: Why your first Rust FizzBuzz implementation may not work

#62
post #34
post #31

Earlier quoted context omitted.

Weird to see this mix of a very imperative for-range iterative loop with a very functional pattern match, which makes it look similar to an SML or OCaml solution to FizzBuzz. I guess this is the definition of multi-paradigm right here. Will Rust's type checker warn you of a non-exhaustive pattern match?

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)

Although I love pattern matching, I find the solution with 'if' more legible and no less functional.

Re: Why your first Rust FizzBuzz implementation may not work

#63
post #31
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

Weird to see this mix of a very imperative for-range iterative loop with a very functional pattern match, which makes it look similar to an SML or OCaml solution to FizzBuzz. I guess this is the definition of multi-paradigm right here. Will Rust's type checker warn you of a non-exhaustive pattern match?

> Will Rust's type checker warn you of a non-exhaustive pattern match?

It refuses to compile entirely.

Re: Why your first Rust FizzBuzz implementation may not work

#64
post #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…

Doesn't type inference stop at function boundaries, though? I'll grant you that idiomatic Haskell uses type annotations for function signatures (unlike idiomatic OCaml), but it is optional (which is convenient in a REPL).

Re: Why your first Rust FizzBuzz implementation may not work

#65
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.

:D

If you have the time, as you do this, I'd love to hear about your experience. Email me any time.

(I maintain Rust's docs, and am also starting to write some introductory curriculum. Hearing from people like you is _invaluable_.)

Re: Why your first Rust FizzBuzz implementation may not work

#66
post #39

Earlier quoted context omitted.

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.

I would suggest you port over a project that you are already familiar with. It's easier to learn a new syntax when you don't have to grapple with implementation as well. And you get to have an objective comparison of the same project implemented 2 different ways.

I agree with this, but I will say that sometimes, you end up structuring a program differently due to the language. This happens a lot in Rust.

It's still easier when you've solved the problem previously, however.

Re: Why your first Rust FizzBuzz implementation may not work

#67
post #49
post #31

Earlier quoted context omitted.

Weird to see this mix of a very imperative for-range iterative loop with a very functional pattern match, which makes it look similar to an SML or OCaml solution to FizzBuzz. I guess this is the definition of multi-paradigm right here. Will Rust's type checker warn you of a non-exhaustive pattern match?

Rust was first conceived by an avid Ocamler, and it was originally implemented in Ocaml too. Although the pot has been stirred quite a bit since those early days, the influence still remains, including the expression heavy programming style, pattern matching, 'let's, HM inference, and `var: T` declaration syntax. Whilst Rust is quite procedural and (you rarely use recursion), it often feels quite functional due to th…

Small note, technically Rust never did HM, and now we _certainly_ don't. It's still inference, just not that algorithm.

Re: Why your first Rust FizzBuzz implementation may not work

#68
post #46
post #41

Earlier quoted context omitted.

But shouldn't they (String and slice) have some common super type to make this all easy to use ?

I don't think a common ancestor is how you want to do this. Instead, I'd encapsulate the common behavior in a trait (a.k.a. an interface, in other languages), and then write functions that accept any parameters that implement that trait. In Rust, you can do this even on "built-in" types like strings. For an example, see the `print_me` function below, which operates on both string types using a trait that I've defined…

http://doc.rust-lang.org/std/str/trait.Str.html ?

Re: Why your first Rust FizzBuzz implementation may not work

#69
> There is a trade‐off here for them; as a general rule, such languages have immutable strings

This is a bit disingenuous. I understand what he's aiming at, and he also mentions StringBuilder later on, but saying that a GC necessatites immutable strings is simply not true.

As a counterexample: PHP has mutable strings and uses copy-on-write in situations where it "feels" that conflicts could occur. (Granted PHPs rules on how it handles its variables is a bit arbitrary and magical, and PHP didn't have a GC till version 5.3 .. but the argument still stands.)

Re: Why your first Rust FizzBuzz implementation may not work

#70
post #23

Earlier quoted context omitted.

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…

Doesn't type inference stop at function boundaries, though? I'll grant you that idiomatic Haskell uses type annotations for function signatures (unlike idiomatic OCaml), but it is optional (which is convenient in a REPL).

Yes, it does, but that's a deliberate design decision, not a flaw. We decided enforcing this idiom was a good idea.
Post reply on HN