Writing Crates for Complete Beginners: A Tour of Turtle
By Sunjay Varma
Link to slides: slides.com/sunjay/tour-of-turtle
RustConf 2018
Talk Outline
- The Turtle Crate
- How does turtle work?
- Designing a crate for complete beginners
Link to slides: slides.com/sunjay/tour-of-turtle
@sunjay03
Rust Resources
@sunjay03
Online Tutorials/Websites
- Rustlings
- into_rust()
- A Gentle Introduction to Rust
- and many more!
Podcasts/YouTube Channels
Even more resources listed here:
@sunjay03
My goal with turtle is to create the resources and community we need in order to make Rust a language that anyone can learn.
The Turtle Crate
@sunjay03
@sunjay03
Pen
Turtle Legs?
Turtle Shell
Turtle
@sunjay03
@sunjay03
Source code for these images can be found in the examples/ directory in the turtle GitHub repo
Methods on the Turtle struct
Movement & Rotation:
- turtle.forward
- turtle.backward
- turtle.right
- turtle.left
Speed, Position, & Heading:
- turtle.set_speed
- turtle.go_to
- turtle.set_heading
- turtle.turn_towards
Pen Control:
- turtle.set_pen_size
- turtle.set_pen_color
- turtle.pen_down
- turtle.pen_up
Shape Filling & Turtle Visibility:
- turtle.begin_fill
- turtle.end_fill
- turtle.hide
- turtle.show
See the complete list in the documentation: docs.rs/turtle
@sunjay03
Turtle Graphics
TO Square
REPEAT 4 [ FD 100 RT 90 ]
END
TO Flower
SETPC [255 000 255] SETPENSIZE [4 4]
CS HT REPEAT 36 [ PU FD 4 PD Square LT 10 ]
SETPENCOLOR [0 0 0] SETPENSIZE [1 1] PU HOME PD
END
Flower
"flower.lgo" from:
vlado.fmf.uni-lj.si/educa/logo/ferdoe.htm
The Turtle Robot
The Logo Programming Language
@sunjay03
Fun fact: My mom introduced me to Logo when I was 12 and I used it to draw a lot of pretty neat pictures back in the day.
The Python turtle Module
The Rust turtle Crate
import turtle
for i in xrange(4):
turtle.forward(200)
turtle.right(90)
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
Modifies "global mutable state" in the turtle module
Creates a new turtle explicitly
The "mut" on the variable above lets us modify the position and rotation of the turtle here
@sunjay03
Tells you exactly how to fix the error
How does turtle work?
Image from: examples/heart.rs in turtle GitHub repo
@sunjay03
extern crate turtle;
use turtle::{Turtle, Color};
fn main() {
let mut turtle = Turtle::new();
turtle.drawing_mut().set_background_color("#112244");
turtle.wait_for_click();
turtle.pen_up();
turtle.backward(160.0);
turtle.right(90.);
turtle.forward(110.);
turtle.pen_down();
turtle.set_speed("faster");
dragon(&mut turtle, -90., 11, 0., 255.);
turtle.hide();
}
/// Draw the dragon curve by simulating folding a strip of paper
fn dragon(
turtle: &mut Turtle,
fold_direction: f64,
num_folds: usize,
color_start: f64,
color_end: f64
) {
let color_mid = (color_start + color_end) * 0.5;
if num_folds == 0 {
// mapping a color number 0-255 to an rgb gradient.
turtle.set_pen_color(Color {
red: ((color_mid - 128.).abs() * 2.).floor(),
green: color_mid,
blue: 160.,
alpha: 1.,
});
return turtle.forward(10.);
}
// draw a left to right strip (which has a left turn in the middle)
dragon(turtle, -90., num_folds - 1, color_start, color_mid);
turtle.right(fold_direction);
// draw a right to left strip (which has a right turn in the middle)
dragon(turtle, 90., num_folds - 1, color_mid, color_end);
}
This code only gives instructions to the turtle and ignores the window, events, etc.
There is no event loop, window management, or rendering code here.
Code from examples/dragon.rs in turtle GitHub repo
Contributed by @exoticorn
@sunjay03
An Event Loop
"Manish asked himself: Is that an event loop?"
User interacts with your application
Application renders your drawings on the screen...
Event loop quickly switches back and forth between these
...and runs your program as fast as possible
Hmm...
*click*
*type*
*click*
Wow! Sunjay is SO cool!
@sunjay03
Attempt #1: Multithreaded
User's Program
main thread
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
Turtle Event Loop
background thread
spawns new thread
waits for the window to be closed before ending the main thread
opens window
starts drawing & handling events
sends drawing command messages
@sunjay03
share state without blocking each other for too long
@sunjay03
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
let mut i = 0;
while turtle.is_window_open() {
turtle.render();
if i < 4 {
turtle.forward(200.0);
turtle.right(90.0);
i += 1;
}
}
}
Before
After
manually managing the event loop
@sunjay03
Attempt #2: Multiprocessing
User's Program
main thread
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
Turtle Event Loop
background thread
opens window
starts drawing & handling events
@sunjay03
spawns new thread
waits for the window to be closed before ending the main thread
sends drawing command messages
share state without blocking each other for too long
process
process
between processes
keep state in sync between both processes
main thread #2
#1
#1
The PR that saved the day: github.com/sunjay/turtle/pull/31
@sunjay03
@sunjay03
@sunjay03
@sunjay03
@sunjay03
Big Plans For The Future!
- Multiple turtles
- 3D drawing
- Text rendering support
- Buttons and text fields for input
- Asynchronous turtles using async/await/Future
- Web assembly support
- and much, much more!
@sunjay03
Try out turtle today!
Image from examples/maze in turtle GitHub repo
@sunjay03
Designing a crate for complete beginners
Tips to make your crates accessible to a wider audience
Image from: github.com/sunjay/turtle/pull/39
@sunjay03
Docs · Audience · Examples · Guide
Design for the audience that makes sense for your crate
.
.
Level of experience
You don't need to be doing this...
.
.
Level of experience
.
.
Level of experience
...in order to do this
.
.
Level of experience
@sunjay03
@sunjay03
cargo test
Runs all of the tests in a Rust project
--features test
Required by turtle to avoid lots of problems
#[cfg(all(test, not(feature = "test")))]
compile_error!("Make sure you run tests with `cargo test --features test`");
Good Documentation
@sunjay03
- Writing documentation that is actually good takes some thought
- Think about the person using your documentation
- What do they already know? What do I need to explain to them so that they understand what they need to do?
- Make sure they get the most important information first
- Write most of your documentation as you write code so you don't forget what you need to write down
Good Documentation
@sunjay03
Good Documentation
@sunjay03
Good Documentation
Links to websites that explain concepts so that we don't have to explain them ourselves
@sunjay03
Good Documentation
Help people get around your documentation quickly
@sunjay03
Examples
@sunjay03
Examples
@sunjay03
Examples
@sunjay03
For demonstrating a specific method:
For full examples of using your crate:
cargo run --example circle
These examples are tested automatically
A Guide
@sunjay03
The Rust API Guidelines
@sunjay03
Read the full guidelines here:
Thank you!
Please go try turtle out!
@sunjay03
Thank you everyone who contributes code and everyone who opens issues!
@sunjay03
Thank you!
Link to slides: slides.com/sunjay/tour-of-turtle
Writing Crates for Complete Beginners: A Tour of Turtle
By Sunjay Varma
Writing Crates for Complete Beginners: A Tour of Turtle
- 2,836