Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Learning Rust, Part 5 (foon.uk)
48 points by rogual on March 19, 2016 | hide | past | favorite | 8 comments


A comment/correction `io` is stable, its just `chars` directly on a type that implements `Read` that is still unstable, the majority of `std::io` is stable these days.


Thanks for the clarification. What's the idiomatic way to read one character from stdin?


The `bytes()` iterator is stable and provides a stream of u8 (well io::Result<u8>) which is sufficient for what you want. I don't think there's a good way to decode an iterator of bytes (which bytes isn't either way, but it could be adapted) to a chars iterator at the moment.


Thank you. Bytes will do just fine. I'm glad Rust is pedantic about bytes vs. chars.


To elaborate slightly further, char in Rust is four bytes, as it represents a Unicode Scalar Value. So the chars iterator isn't yet stable because it's not clear what should be done in the case of a read of a partial char. This is, of course, fixable, there's just a lot to do, and that's the question for this specific API.


With interesting things happening in Rust-land, I decided to take another run at Rust and see how it's improved in the last year.

This isn't really a blog or a tutorial, it's just me stumbling around and trying stuff. I enjoy reading this sort of thing when other people do it, so I hope you get something out of it too.

Previously: https://news.ycombinator.com/item?id=8546546


> When the Rust people say “always use the nightlies”, they mean ALWAYS use the nightlies.

AFAIK, the Rust people haven't said that for quite some time. There are still a number of unstable area (the most annoying to me being benchmarking) but by and large stable is very much usable.

In your case, the code could be simplified (and would work on stable) by using a bytes iterator (and an actual for loop):

    fn main() {
        let mut state = mkstate();
        for it in stdin().bytes() {
            update(&mut state, it.unwrap());
            draw(&state);
        }
    }
replace a few `char` by `u8` and change key_dir to:

    match input {
        b'h' => Coord(-1, 0),
        b'j' => Coord(0, 1),
        b'k' => Coord(0, -1),
        b'l' => Coord(1, 0),
        _ => Coord(0, 0)
    }
(I used unwrap because the stdin errors are not handled anyway, might as well panic)

edit: conventionally, when structures aren't "raw" they're initialised via a `new()` method, so `mkstate` would usually be `impl State { fn new() -> State { … } }`.

And derive(Default) is necessary because, well, you're using default values for your structs. From what I've seen that's mostly done when partial overrides of default value makes sense (`Struct { f: v, ..Default::default() }` will fill any value which isn't provided by whatever's in `Default`) which isn't the case here.

You could get rid of it by implementing initialisations explicitly, something along the lines of:

    impl State {
        fn new() -> State {
            let mut state = State {
                // or add a new() on them as well
                position: position::State { objects: Vec::new() },
                graphics: graphics::State { objects: Vec::new() }
            };
            
            mktest(&mut state, 42, Coord(1, 1), '@');
            mktest(&mut state, 57, Coord(8, 8), '$');

            state
        }
    }
I'd also suggest deriving Copy on Coord (makes the structure "pass by copy" rather than "pass by move", so you don't have to clone it explicitly).

And you could `impl Add for Coord` to replace `vadd(old_position, dir)` by `old_position + dir`

(I believe Rust code also tends to use more methods, but I'm guessing you like free functions).

You could also replace the inner State structs by type aliases, the struct doesn't seem to have much value, so

    mod graphics {
        pub struct State {
            pub objects: Vec<Sprite>
        }
    }
=>

    mod graphics {
        pub type State = Vec<Sprite>
    }
and remove the indirections through `objects` (and you get a "free new" on graphics::State and position::State as they're now just aliases for Vec<_>)


Small errata:

    fn process(state: &State)
still has a recursive call after it's been converted to use a loop.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: