Skip to content

Instantly share code, notes, and snippets.

@steveklabnik
Last active August 29, 2015 14:03
Show Gist options
  • Save steveklabnik/7916d6256a6517e8282e to your computer and use it in GitHub Desktop.
Save steveklabnik/7916d6256a6517e8282e to your computer and use it in GitHub Desktop.
Rust first project

Help the docs!

EDIT: If you read the gist before, I've updated it with my latest version. I'm pretty sure I took care of everyone's comments, thanks so much!

So! The new tutorial will be focused on building several small projects in Rust. This example is the first one: a classic 'guessing game.' This was one of the first programs I wrote when I first learned C. 😄

I'd like the feedback of the community before I actually start writing the guide. So this code will be the final code of the first real example Rust programmers see. So I want it to be good. I don't claim this code is good, I just worked something out real quick. Oh, and this is tracking master.

The idea is that I will slowly build from hello world to this final code in steps, introducing one concept at a time. Here are the concepts I'd like a Rust programmer to understand by the time they're done:

Concepts

  • If
  • Functions
    • return (wrt semicolons)
  • comments
  • Testing
  • attributes
  • stability markers
  • Crates and Modules
  • visibility
  • Compound Data Types
  • Tuples
  • Structs
  • Enums
  • Match
  • Looping
  • for
  • while
  • loop
  • break/continue
  • iterators
use std::io;
use std::rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = std::rand::task_rng().gen_range(1i, 101);
println!("Secret number is {}", secret_number);
let mut guesses: int = 0;
let mut reader = io::stdin();
loop {
println!("Please input guess number {}", guesses + 1);
let input = reader.read_line().ok().expect("Failed to read line");
let input_num = from_str::<int>(input.as_slice().trim());
let num = match input_num {
Some(num) => num,
None => {
println!("Please input a number.");
continue;
}
};
println!("You guessed: {}", num);
guesses += 1;
match num.cmp(&secret_number) {
Less => println!("Too small!"),
Greater => println!("Too big!"),
Equal => {
println!("You win!");
break;
},
}
}
println!("You took {} guesses!", guesses);
}
@bachm
Copy link

bachm commented Jun 27, 2014

gen_range will return a number in the range [low, high). There's an opportunity to demonstrate how ranges work by pointing this behaviour out.

@cgaebel
Copy link

cgaebel commented Jun 27, 2014

I think using .unwrap should be replaced with .expect. It's better style and gives nicer error messages. It's also a good example of the good user-friendly error checking.

@steveklabnik
Copy link
Author

@bachm yes, I screwed it up. Heh. What's funny is that I submitted documentation on that range behavior today...

@cgaebel an excellent addition. Will do that for sure. Thanks!

@vks
Copy link

vks commented Jun 27, 2014

I think the sentences should end in a punctuation mark. (I.e. "Secret number is {}." and "Please input guess number {}.")

@nathantypanski
Copy link

The gen_range behavior that @bachm is talking about can be shown in the code:

use std::io;
use std::rand::Rng;

static LOW: int = 1;
static HIGH: int = 101;

fn main() {
    println!("Guess the number!");

    let secret_number = std::rand::task_rng().gen_range(LOW, HIGH);
    println!("Secret number is {}.", secret_number);

    let mut guesses: int = 0;
    let mut reader = io::stdin();

    println!("The number is between {} and {}.", LOW, HIGH - 1);

    loop {
        // ...
    }

    println!("You took {} guesses!", guesses);
}

Extra concepts demonstrated:

  • Statics (is this a good thing? Traditionally, when I write ranges like this that are likely to change, I'll make them static if it's a simple program.)
  • Variable numbers of arguments to the println!() macro (wtf is the bang ! for? Using multiple args might make it clear it's a macro.).
  • Variable type declarations.
  • The code itself shows how range inclusion works.

Downsides:

  • There's no 1i anymore, and even though it could be included, it would be redundant.
  • Showing more stuff now adds conceptual bulk. We need to shoot for a happy medium.

@FreeFull
Copy link

Since this is an introductory tutorial program, wouldn't it be a good idea to have comments throughout it, explaining various finer points about how Rust handles things (such as, ranges not including the last element, or the existence of Result/Option APIs)

Edit: Looking at the concepts, comments is one of them, although the code itself doesn't have any yet.

@caipre
Copy link

caipre commented Jul 5, 2014

I think it's probably worthwhile to define a function other than main to demonstrate return as you said. You might want to avoid discussion of ownership early on though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment