4 ms·
I'm currently learning rust and it's an interesting experience dealing with libraries where I can't judge which parts of libraries are typical rust and which pa
by Lerc 11y ago
I'm currently learning rust and it's an interesting experience dealing with libraries where I can't judge which parts of libraries are typical rust and which parts are just design decisions by the library developer.
Since Rust is so new, perhaps there is no real difference, but the piston example shows some ideas that I'm not sure I like but I also don't know if that is just how things are done in the Rust world.
let window: PistonWindow =
WindowSettings::new("Hello Piston!", [640, 480])
.exit_on_esc(true).build().unwrap();
for e in window {
e.draw_2d(|c, g| {
clear([1.0; 4], g);
rectangle([1.0, 0.0, 0.0, 1.0], // red
[0.0, 0.0, 100.0, 100.0],
c.transform, g);
});
}
That's iterating on a window which seems an odd choice.
The functions clear and rectangle seem to me to be things that should be in traits rather than functions that require a parameter to say what the target of the drawing function is.
- bsder 11y agoTake a look at the underlying Glium (OpenGL) library. It makes some very specific decisions in order to make OpenGL programming far more efficient.
- hughes 11y agoSingle-character variable names really do not help this introductory example.
- Gankro 11y agoPiston is pretty quirky, honestly. The window builder is pretty vanilla, but the event-processing-for-loop stuff is super quirky. The `e` that is yielded by iterating the window is the window itself WHAT Especially because the examples use stuff that is basically impossible to find in the docs (even though the docs are auto-generated from the source!). The modularity makes it really hard to tell how anything works, what anything is, or what functionality anything has.
- Retra 11y agoYou can also iterate over an `Option` to get its contents: let s = Some(10u32); for val in s { println!("{}", val); } So it's not a completely foreign concept... but maybe they went too far with it?
- Gankro 11y agoYeah both are examples of the designer being a bit "cute". The piston thing is however totally idiomatic and recommended by the piston devs, while I've never seen anyone actually loop over an Option in real code. Though it wouldn't be super terrible if it was idiomatic. I personally prefer to do `s.map(|val| { ... }), but there's a contingent that argues that `map` shouldn't be used purely for side-effects, and should instead be used for, you know, mapping. We've oft argued that if you want to consume an iterator, it aught to be with a `for` loop, so it might make sense to say the same about an Option? Option is such a trivial and core type that you basically end up with 4 ways to do everything you could think of, because semantically distinct conventions all end up doing the exact same thing: for x in data { println!("{}", x) } if let Some(x) = data { println!("{}", x) } data.map(|x| { println!("{}", x) }); match data { Some(x) => println!("{}", x), _ => () } The fact that you can loop over an option is kind of a side-effect of a lot of our APIs taking "thing that is iterable", and evidently it was convenient to provide that for Option (which is after all just a really degenerate collection). You can of course `match` and `if let` an Option because it's an enum, but because there's two cases and one has no state, they end up being completely equivalent (the `_ =>` branch is just an `else`). Then finally you can `map` over an Option because... It's Option. That's what you do with optional types, dangit!
- tinco 11y agoI've been building a small game on Piston together with a friend. It's in a super early exploratory fase. You can see how we deal with the event loop here: https://github.com/tinco/super-susano/blob/master/src/main.rs#L175 https://github.com/tinco/super-susano/blob/master/src/main.r... That calls into the draw loop here: https://github.com/tinco/super-susano/blob/master/src/engines/graphics.rs#L20 https://github.com/tinco/super-susano/blob/master/src/engine...