% Rust Cheatsheet
Int to string
Use ToStr
.
let x: int = 42;
let y: ~str = x.to_str();
String to int
Use FromStr
, and its helper function, from_str
.
let x: Option<int> = from_str("42");
let y: int = x.unwrap();
Int to string, in non-base-10
Use ToStrRadix
.
use std::num::ToStrRadix;
let x: int = 42;
let y: ~str = x.to_str_radix(16);
String to int, in non-base-10
Use FromStrRadix
, and its helper function, from_str_radix
.
use std::num::from_str_radix;
let x: Option<i64> = from_str_radix("deadbeef", 16);
let y: i64 = x.unwrap();
Use File::open
to create a File
struct, which implements the Reader
trait.
use std::path::Path;
use std::io::fs::File;
let path : Path = Path::new("Doc-FAQ-Cheatsheet.md");
let on_error = || fail!("open of {:?} failed", path);
let reader : File = File::open(&path).unwrap_or_else(on_error);
Use the lines
method on a BufferedReader
.
use std::io::BufferedReader;
# use std::io::MemReader;
# let reader = MemReader::new(~[]);
let mut reader = BufferedReader::new(reader);
for line in reader.lines() {
print!("line: {}", line);
}
Use the find_str
method.
let str = "Hello, this is some random string";
let index: Option<uint> = str.find_str("rand");
The Container
trait provides the len
method.
let u: ~[u32] = ~[0, 1, 2];
let v: &[u32] = &[0, 1, 2, 3];
let w: [u32, .. 5] = [0, 1, 2, 3, 4];
println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5
Use the iter
method.
let values: ~[int] = ~[1, 2, 3, 4, 5];
for value in values.iter() { // value: &int
println!("{}", *value);
}
(See also mut_iter
which yields &mut int
and move_iter
which yields int
while consuming the values
vector.)
struct Foo {
myfunc: fn(int, uint) -> i32
}
struct FooClosure<'a> {
myfunc: 'a |int, uint| -> i32
}
fn a(a: int, b: uint) -> i32 {
(a as uint + b) as i32
}
fn main() {
let f = Foo { myfunc: a };
let g = FooClosure { myfunc: |a, b| { (a - b as int) as i32 } };
println!("{}", (f.myfunc)(1, 2));
println!("{}", (g.myfunc)(3, 4));
}
Note that the parenthesis surrounding f.myfunc
are necessary: they are how Rust disambiguates field lookup and method call. The 'a
on FooClosure
is the lifetime of the closure's environment pointer.
Phantom types are those that cannot be constructed at compile time. To express these in Rust, zero-variant enum
s can be used:
enum Open {}
enum Closed {}
Phantom types are useful for enforcing state at compile time. For example:
struct Door<State>(~str);
struct Open;
struct Closed;
fn close(Door(name): Door<Open>) -> Door<Closed> {
Door::<Closed>(name)
}
fn open(Door(name): Door<Closed>) -> Door<Open> {
Door::<Open>(name)
}
let _ = close(Door::<Open>(~"front"));
Attempting to close a closed door is prevented statically:
let _ = close(Door::<Closed>(~"front")); // error: mismatched types: expected `main::Door<main::Open>` but found `main::Door<main::Closed>`
Description C signature Equivalent Rust signature
no parameters void foo(void);
fn foo();
return value int foo(void);
fn foo() -> c_int;
function parameters void foo(int x, int y);
fn foo(x: int, y: int);
in-out pointers void foo(const int* in_ptr, int* out_ptr);
fn foo(in_ptr: *c_int, out_ptr: *mut c_int);
Note: The Rust signatures should be wrapped in an extern "ABI" { ... }
block.
You might see things like this in C APIs:
typedef struct Window Window;
Window* createWindow(int width, int height);
You can use a zero-element enum
(phantom type) to represent the opaque object handle. The FFI would look like this:
enum Window {}
extern "C" {
fn createWindow(width: c_int, height: c_int) -> *Window;
}
Using a phantom type ensures that the handles cannot be (safely) constructed in client code.
For small examples, have full type annotations, as much as is reasonable, to keep it clear what, exactly, everything is doing. Try to link to the API docs, as well.
Similar documents for other programming languages: