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.
Why your first Rust FizzBuzz implementation may not work
61–70 of 139 posts
Re: Why your first Rust FizzBuzz implementation may not work
#62Earlier 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)
Re: Why your first Rust FizzBuzz implementation may not work
#63Putting 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?
It refuses to compile entirely.
Re: Why your first Rust FizzBuzz implementation may not work
#64The 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…
Re: Why your first Rust FizzBuzz implementation may not work
#65Putting 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…
: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
#66Earlier 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.
It's still easier when you've solved the problem previously, however.
Re: Why your first Rust FizzBuzz implementation may not work
#67Earlier 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…
Re: Why your first Rust FizzBuzz implementation may not work
#68Earlier 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…
Re: Why your first Rust FizzBuzz implementation may not work
#69This 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
#70Earlier 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).