int* abc() {
int x = 1;
return &x;
}
// Create the vector
vector<int> x;
x.push_back(1);
x.push_back(2);
x.push_back(3);
// Get an iterator
vector<int>::iterator itr = x.begin();
int j=0;
for (itr; itr !=x.end(); itr++) {
x.push_back(j); // Uh oh!
j++;
cout << j << " .. ";
}
if a > 1 {
println!("{:?}", a);
}
let mut i: i32 = 0;
loop {
if i > 10 { break; }
i += 1;
println!("{:?}", i);
}
fn multiply(x: i32, y: i32) -> i32 {
return x*y // The return statement is unnecessary, this will be explained later
}
Semicolons have meaning!
let b = 3i32;
let a = if b > 1 {
let mut c = b - 5;
c = c * b; // Removing these two semicolons cause errors
c // This "returns" the value of c, due to the lack of semicolon
} else {
1i32
};
fn greater(a: i32, b: i32) -> i32 {
if a > b {
a
} else {
b
}
}
Switch-case just got a makeover
let number = 5u32;
let size = match number {
0 => "none",
2 | 3 => "tiny",
4...7 => "small",
8...20 => "medium",
_ => "large"
};
// Multiple statements in a match work!
match number {
2 | 8 | 9 => {
let mut c = 1;
c += number;
println!("The incremented number is {}", c);
},
_ => println!("We don't have the ability to increment this number, sorry")
}
let pair = (4u32, 5u32);
let (a, b) = pair; // a=4, b=5
let (b, a) = (a, b); // Swap!
let smaller = match pair {
(x, y) if x < y => x,
(_, y) => y
};
match pair {
(0, 0) => println!("Origin"),
(0, y) => println!("Y-axis, coordinate {}", y),
(x, 0) => println!("X-axis, coordinate {}", x),
(x, y) => {
let distance = ((x*x + y*y) as f32).sqrt();
println!("Point is ({}, {}), and {} units from origin", x, y, distance);
}
};
struct Point {
pub x: i32,
pub y: i32
}
let p = Point {x: 0, y: 0};
println!("X coordinate is {}", p.x)
enum Shape {
Circle(Point, u32),
Rectangle(Point, Point)
}
// Real world example
enum Option<T> {
Some(T),
None
}
let origin = Point {x: 0, y: 0};
let circ = Shape::Circle(origin, 10);
let perimeter = match shape {
Circle(_, r) => 2*pi*r,
Rectangle(p1, p2) => 2*abs(p2.x - p1.x) + 2*abs(p2.y - p1.y)
}
// But wait, we can match on structs too!
let perimeter = match shape {
Circle(_, r) => 2*pi*r,
Rectangle(Point {x: x1, y: y1}, Point {x: x2, y: y2}) =>
2*abs(x2 - x1) + 2*abs(y2 - y1)
}
// Patterns nest pretty well
match point {
Point {x: 2...6, y: -1...5} => println!("I like this point"),
_ => println!("I do not like this point")
}
enum Option<T> {
Some(T),
None
}
fn maybe_sqrt(x: i32) -> Option<u32> {
if x >= 0 {
Some(sqrt(x) as u32)
} else {
None
}
}
impl Point {
fn distance(&self) -> f32 { // Called as point.distance()
((self.x*self.x + self.y*self.y) as f32).sqrt()
}
fn random() -> Point { // Called as Point::random()
Point {
x: 4, // Chosen by fair dice roll
y: 4 // Guaranteed to be random
}
}
}
// Haskell's type classes, anyone?
trait Pointy {
fn poke(&self, at: &str);
// One can also give full function bodies here
}
impl Pointy for Point {
fn poke(&self, at: &str) {
println!("Poked {}", at);
}
}
fn poke_forever<T: Pointy>(pointy: T, at: &str) {
loop {
pointy.poke(at)
}
}
let x = 5i8;
let y = x;
println!("x is {:?}", x); // y was copied from x
let x = vec![1u8, 2u8, 3u8]; // A vector
let y = x; // the vector was "moved"
println!("y is {:?}", y);
// Will not work, the vector is "owned" by y
// println!("x is {}", x)
fn abc(x: Vec<u8>) {
// do something
}
let myvec = vec![1u8, 2u8, 3u8];
abc(myvec); // myvec moved into function, cannot be used after this
let x = vec![1u8, 2u8, 3u8];
let y = &x; // the vector was "borrowed"
let c = x.clone(); // Explicit copy
println!("x is {:?}", x);
println!("y is {:?}", *y);
fn abc(x: &Vec<u8>) {
// do something
}
let myvec = vec![1u8,2u8,3u8];
abc(&myvec); // Passes a borrowed reference
// Still can use myvec here
let mut x = vec![1u8,2u8,3u8];
{
let y = &x; // the pointer was "borrowed"
// x.push(1); // Not allowed, x is currently borrowed and cannot be mutated
// y.push(1); // Not allowed, y is not a mutable reference
}
x.push(1); // The borrow was "returned", we can mutate now
let mut x = vec![1u8,2u8,3u8];
{
let y = &mut x; // the pointer was "borrowed", mutably
// x.push(1); // Still not allowed, x is currently borrowed and cannot be mutated
// println!("x is {}", x) // also not allowed, y is mutating this
y.push(1); // Allowed, y is a mutable reference
}
x.push(1) // The borrow was "returned", we can mutate now
struct Polygon {points: Vec<Point>};
impl Point {
// This one moves
fn draw_move(self) {
// ...
}
// This one borrows
fn draw_borrow(&self) {
// ...
// after calling p.draw_borrow() I can still use p
}
// This one borrows mutably
fn draw_borrow_mut(&mut self) {
// ...
// I can mutate self here
}
}
// (*polygon).draw_borrow() dereference not necessary
let mut x = Box::new(1); // On the heap
*x = 2;
// Type Box<u32>
// Also gets moved, not copied
fn abc() {
let x = Box::new(1); // malloc() happened
// do stuff with x or *x
// free() happened
}
fn def() -> Box<u32>{
let x = Box::new(1); // malloc() happened
// do stuff with x or *x
x // x returned to outer owner
}
let pair = (Box::new(1), Box::new(2));
let (a, b) = pair;
// The boxes were moved out of `pair`, cannot use it anymore
let pair = (Box::new(1), Box::new(2));
{
let (ref a, ref b) = pair;
// a, b are borrowed references now, so everything is fine
// use `ref mut` for mutable references
}
// Works in match statements too!
let maybe_heap = Some(Box::new(1));
match maybe_heap {
Some(ref x) => println!("{}", x),
None => println!("No variable")
}
let mut fixed_len_vec = [1,2,3]; // Of type [u32, ..3]
fixed_len_vec[1] = 2;
let mut buffer = vec![1,2,3]; // Of type Vec<u32>
buffer.push(20); // Now it is of length 4!
let slice = &buffer[0..2]; // Of type &[u32]
let slice = &[1,2,3]; // Same
let owned = "Manish".to_string(); // of type String
let static_slice = "Manish"; // type `&'static str`
let slice = &owned[0..3]; // type &str . Basically a borrowed "view" into the String
extern crate core;
use std::{mem, ptr};
fn main() {
let y = *dangle() + 1;
// Segfault.
}
fn dangle() -> Box<u32> {
unsafe {
// Null pointers!
let mut p: *mut int = ptr::null_mut();
let b = Box::new(1u32); // Heap memory, will be deallocated at the end of this function
ptr::write(p, *b);
mem::transmute(p) // Converts to box and .. uh oh .. returns!
}
}
use std::sync::mpsc::*;
use std::thread::spawn;
let (tx, rx) = channel();
spawn(move || {
tx.send(1); // works!
});
let x = rx.recv();
use std::sync::mpsc::*;
use std::thread::spawn;
let (tx, rx) = channel();
spawn(move || {
let x = Box::new(1);
tx.send(x); // works!
});
let x = rx.recv();
use std::sync::mpsc::*;
use std::thread::spawn;
let (tx, rx) = channel();
spawn(move || {
let x = Box::new(1);
tx.send(&x); // nope
});
let x = rx.recv();
use std::sync::mpsc::*;
use std::thread::spawn;
use std::rc::Rc;
let (tx, rx) = channel();
spawn(move || {
let x = Rc::new(1);
// refcounted pointer
// not threadsafe
tx.send(x.clone()); // nope
});
let x = rx.recv();
test.rs:18:1: 18:6 error: the trait `core::marker::Send` is not implemented for the type `alloc::rc::Rc<i32>` [E0277] test.rs:18 spawn(move || { ^~~~~ test.rs:18:1: 18:6 note: `alloc::rc::Rc<i32>` cannot be sent between threads safely test.rs:18 spawn(move || {