リスト : トレイト Add の定義
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
リスト : 演算子の多重定義
use std::ops::Add;
#[derive(Debug, Copy, Clone)]
struct Point {
x: f64, y: f64
}
#[derive(Debug, Copy, Clone)]
struct Point3d {
x: f64, y: f64, z: f64
}
impl Point {
fn new(x0: f64, y0: f64) -> Point {
Point { x: x0, y: y0 }
}
}
impl Point3d {
fn new(x0: f64, y0: f64, z0: f64) -> Point3d {
Point3d { x: x0, y: y0, z: z0 }
}
}
// 左辺と右辺でデータ型が同じ場合
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y
}
}
}
impl Add for Point3d {
type Output = Point3d;
fn add(self, other: Point3d) -> Point3d {
Point3d {
x: self.x + other.x,
y: self.y + other.y,
z: self.z + other.z
}
}
}
// 右辺と左辺でデータ型が違う場合
impl Add<Point3d> for Point {
type Output = Point3d;
fn add(self, other: Point3d) -> Point3d {
Point3d {
x: self.x + other.x,
y: self.y + other.y,
z: other.z
}
}
}
impl Add<Point> for Point3d {
type Output = Point3d;
fn add(self, other: Point) -> Point3d {
Point3d {
x: self.x + other.x,
y: self.y + other.y,
z: self.z
}
}
}
fn main() {
let p1 = Point::new(1.0, 1.0);
let p2 = Point::new(2.0, 2.0);
let p3 = Point3d::new(10.0, 10.0, 10.0);
let p4 = Point3d::new(20.0, 20.0, 20.0);
println!("{:?}", p1 + p2);
println!("{:?}", p3 + p4);
println!("{:?}", p1 + p3);
println!("{:?}", p4 + p2);
}
Point { x: 3, y: 3 }
Point3d { x: 30, y: 30, z: 30 }
Point3d { x: 11, y: 11, z: 10 }
Point3d { x: 22, y: 22, z: 20 }
リスト : サイズ不定型の簡単な使用例
struct Foo<T: ?Sized> {
buff: T // 大きさが異なる配列でも格納できる
}
fn main() {
let a = [1,2,3];
let b = [1,2,3,4,5,6];
let c = Foo { buff: a };
let d = Foo { buff: b };
let e = Foo { buff: [1,2,3,4,5,6,7,8,9]};
println!("{:?}", c.buff);
println!("{:?}", d.buff);
println!("{:?}", e.buff);
}
[1, 2, 3] [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6, 7, 8, 9]
リスト : トレイト Deref の定義
pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
リスト : トレイト Deref の簡単な使用例
use std::ops::Deref;
struct Foo<T: ?Sized> {
buff: T
}
impl<T> Deref for Foo<T> {
type Target = T;
fn deref(&self) -> &T {
&self.buff
}
}
struct Bar {
num: i32
}
impl Deref for Bar {
type Target = i32;
fn deref(&self) -> &i32 {
&self.num
}
}
fn main() {
let a = Foo { buff: [1,2,3] };
let b = Foo { buff: [4,5,6,7,8,9] };
let c = Bar { num: 123 };
let d = Bar { num: 456 };
println!("{:?}", *a);
println!("{:?}", *b);
println!("{:?}", *c);
println!("{:?}", *d);
}
[1, 2, 3] [4, 5, 6, 7, 8, 9] 123 456
リスト : トレイト DerefMut
pub trait DerefMut: Deref {
fn deref_mut(&mut self) -> &mut Self::Target;
}
リスト : DerefMut の簡単な使用例
use std::ops::{Deref, DerefMut};
struct Bar {
num: i32
}
impl Deref for Bar {
type Target = i32;
fn deref(&self) -> &i32 {
&self.num
}
}
impl DerefMut for Bar {
fn deref_mut(&mut self) -> &mut i32 {
&mut self.num
}
}
fn main() {
let mut c = Bar { num: 123 };
let d = Bar { num: 456 };
println!("{:?}", *c);
println!("{:?}", *d);
*c = 789;
println!("{:?}", *c);
}
123 456 789
リスト : deref の型強制
use std::ops::{Deref, DerefMut};
struct Bar {
num: i32
}
impl Deref for Bar {
type Target = i32;
fn deref(&self) -> &i32 {
&self.num
}
}
impl DerefMut for Bar {
fn deref_mut(&mut self) -> &mut i32 {
&mut self.num
}
}
fn bar(x: &i32) {
println!("{}", x);
}
fn main() {
let mut c = Bar { num: 123 };
let d = Bar { num: 456 };
println!("{:?}", *c);
println!("{:?}", *d);
*c = 789;
println!("{:?}", *c);
bar(&c);
bar(&d);
let e = Box::new(1000);
bar(&e);
let f = Box::new(Bar { num: 2000 });
bar(&f);
}
123 456 789 789 456 1000 2000
リスト : メソッド呼び出しの型強制
use std::ops::Deref;
struct Foo {
num: i32
}
impl Foo {
fn foo(&self) {
println!("{}", self.num)
}
}
struct Bar {
content: Foo
}
impl Deref for Bar {
type Target = Foo;
fn deref(&self) -> &Foo {
&self.content
}
}
fn main() {
let a = Box::new(Foo { num: 123 });
let b = Bar { content: Foo { num: 456 } };
let c = Box::new(Bar { content: Foo { num: 789 } });
a.foo();
b.foo();
c.foo();
}
123 456 789
リスト : Rc<T> の簡単な使用例 (1)
use std::rc::Rc;
#[derive(Clone)]
struct Foo {
num: i32
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Drop foo {}", self.num);
}
}
fn main() {
let a = Rc::new(Foo { num: 123 });
println!("{}", Rc::strong_count(&a));
let x = Box::new(Foo { num: 456 });
println!("{}", x.num);
{
let b = a.clone();
println!("{}", Rc::strong_count(&a));
println!("{}", Rc::strong_count(&b));
let c = &a;
println!("{}", Rc::strong_count(&a));
println!("{}", Rc::strong_count(c));
let y = x.clone();
println!("{}", y.num);
}
println!("{}", Rc::strong_count(&a));
}
1 456 2 2 2 2 456 Drop foo 456 1 Drop foo 456 Drop foo 123
リスト : Rc<T> の簡単な使用例 (2)
use std::rc::Rc;
#[derive(Debug)]
struct Foo {
num: i32
}
fn main() {
let a = Box::new(Foo { num: 123 });
let b = *a; // move
// println!("{}", a.num); コンパイルエラー
println!("{}", b.num);
let c = Rc::new(Foo { num: 456 });
// let x = *c; Rc の場合は単純に move することはできない
{
let d = c.clone();
// 参照カウンタが 1 よりも多いと Err
match Rc::try_unwrap(d) {
Ok(x) => println!("{}", x.num),
Err(x) => println!("error {:?}", x)
}
}
// 参照カウンタが 1 ならば Ok
match Rc::try_unwrap(c) {
Ok(x) => println!("{}", x.num),
Err(x) => println!("error {:?}", x)
}
}
123
error Foo { num: 456 }
456
fn try_unwrap(this: Rc<T>) -> Result<T, Rc<T>>
リスト : 簡単な連結リスト (Rc 版)
use std::rc::Rc;
#[derive(Debug)]
enum List {
Nil,
Cons(i32, Rc<List>)
}
use List::*;
impl List {
fn new() -> Rc<List> {
Rc::new(Nil)
}
fn cons(x: i32, xs: &Rc<List>) -> Rc<List> {
Rc::new(Cons(x, xs.clone()))
}
}
impl Drop for List {
fn drop(&mut self) {
match *self {
Nil => println!("drop Nil"),
Cons(x, _) => println!("drop {}", x)
}
}
}
fn main() {
let a = List::new();
println!("{:?}", a);
{
let b = List::cons(1, &a);
println!("{:?}", a);
println!("{:?}", b);
println!("{}", Rc::strong_count(&a));
println!("{}", Rc::strong_count(&b));
{
let c = List::cons(2, &b);
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
println!("{}", Rc::strong_count(&a));
println!("{}", Rc::strong_count(&b));
println!("{}", Rc::strong_count(&c));
}
println!("{}", Rc::strong_count(&a));
println!("{}", Rc::strong_count(&b));
}
println!("{}", Rc::strong_count(&a));
}
Nil Nil Cons(1, Nil) 2 1 Nil Cons(1, Nil) Cons(2, Cons(1, Nil)) 2 2 1 drop 2 2 1 drop 1 1 drop Nil
リスト : Cell の簡単な使用例
use std::cell::Cell;
struct Foo {
x: i32,
y: Cell<i32>
}
fn main() {
let a = Cell::new(123);
println!("{:?}", a);
println!("{}", a.get());
a.set(456);
println!("{:?}", a);
println!("{}", a.get());
let b = Foo { x: 789, y: Cell::new(999) };
println!("{}. {:?}", b.x, b.y);
b.y.set(1000);
println!("{}, {:?}", b.x, b.y);
let c = Box::new(Cell::new(1.234));
println!("{}", c.get());
c.set(5.678);
println!("{}", c.get());
}
Cell { value: 123 }
123
Cell { value: 456 }
456
789, Cell { value: 999 }
789, Cell { value: 1000 }
1.234
5.678
リスト : RefCell の簡単な使用例
use std::cell::RefCell;
#[derive(Debug)]
struct Foo {
x: i32,
}
impl Drop for Foo {
fn drop(&mut self) {
println!("drop foo {}", self.x);
}
}
#[derive(Debug)]
struct Bar {
foo: RefCell<Foo>
}
fn main() {
let a = RefCell::new(123);
println!("{:?}", a);
{
println!("{}", *a.borrow()); // immutable な参照
}
{
let mut ref_a = a.borrow_mut(); // mutable な参照
*ref_a = 456;
// println!("{}", *a.borrow()); immutable な参照を借りるとパニック
}
println!("{}", *a.borrow()); //immutable な参照
let b = Bar { foo: RefCell::new(Foo { x: 123 })};
println!("{:?}", b);
{
println!("{:?}", *b.foo.borrow()); // immutable な参照
}
{
let mut ref_b = b.foo.borrow_mut(); // mutable な参照
*ref_b = Foo { x: 456 }; // Foo { x: 123 } は廃棄される
}
println!("{:?}", b);
let c = Box::new(RefCell::new(Foo { x: 789 }));
println!("{:?}", c);
{
println!("{}", c.borrow().x); // フィールド x の値を参照する
c.borrow_mut().x = 999; // フィールド x の値を書き換える
println!("{:?}", c);
}
{
let mut ref_c = c.borrow_mut(); // mutable な参照
*ref_c = Foo { x: 1000 }; // Foo { x: 999 } は廃棄される
}
let d = c.into_inner(); // メソッド into_inner() は中身のデータを move する
// println!("{:?}", c); コンパイルエラーになる
println!("{:?}", d);
}
RefCell { value: 123 }
123
456
Bar { foo: RefCell { value: Foo { x: 123 } } }
Foo { x: 123 }
drop foo 123
Bar { foo: RefCell { value: Foo { x: 456 } } }
RefCell { value: Foo { x: 789 } }
789
RefCell { value: Foo { x: 999 } }
drop foo 999
Foo { x: 1000 }
drop foo 1000
drop foo 456
リスト : Cell の簡単な使用例 (その2)
use std::cell::Cell;
struct Foo {
num: Cell<i32>
}
impl Foo {
fn new(x: i32) -> Foo {
Foo { num: Cell::new(x) }
}
fn get_num(&self) -> i32 {
self.num.get()
}
fn set_num(&self, x: i32) { // immutable な参照でも更新できる
self.num.set(x)
}
}
fn main() {
let a = Foo::new(100);
let b = &a;
let c = &a;
println!("{}", a.get_num());
println!("{}", b.get_num());
println!("{}", c.get_num());
c.set_num(200);
println!("{}", a.get_num());
println!("{}", b.get_num());
println!("{}", c.get_num());
}
100 100 100 200 200 200
リスト : write! の簡単な使用例
use std::io::{self, Write};
fn main () {
let mut buff = Vec::new();
write!(&mut buff, "hello, world").unwrap();
write!(&mut buff, "{}, {}, {}", 1, 1.2345, "foo bar baz").unwrap();
io::stdout().write(&buff).unwrap();
}
hello, world1, 1.2345, foo bar baz
リスト : Display トレイトの定義
pub trait Display {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error>;
}
リスト : Display トレイトの簡単な実装例
use std::fmt;
struct Point {
x: i32, y: i32
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let a = Point { x: 0, y: 0 };
let b = Point { x: 10, y: 20 };
println!("{}, {}", a, b);
}
(0, 0), (10, 20)
リスト : VecDeque の簡単な使用例
use std::collections::VecDeque;
fn main() {
// スタック (Stack) の動作
let mut s = VecDeque::new();
for x in 0 .. 10 {
s.push_back(x);
}
println!("{:?}", s);
while !s.is_empty() {
println!("{}", s.pop_back().unwrap());
}
// キュー (Queue) の動作
let mut q = VecDeque::new();
for x in 10 .. 20 {
q.push_back(x);
}
println!("{:?}", q);
while !q.is_empty() {
println!("{}", q.pop_front().unwrap());
}
}
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 9 8 7 6 5 4 3 2 1 0 [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 10 11 12 13 14 15 16 17 18 19
リスト : LinkedList の簡単な使用例
use std::collections::LinkedList;
fn main() {
// スタック (Stack) の動作
let mut s = LinkedList::new();
for x in 0 .. 10 {
s.push_back(x);
}
println!("{:?}", s);
while !s.is_empty() {
println!("{}", s.pop_back().unwrap());
}
// キュー (Queue) の動作
let mut q = LinkedList::new();
for x in 10 .. 20 {
q.push_back(x);
}
println!("{:?}", q);
while !q.is_empty() {
println!("{}", q.pop_front().unwrap());
}
}
結果は VecDeque の簡単な使用例と同じ。
リスト : HashMap の簡単な使用例
use std::collections::HashMap;
fn main() {
let mut ht = HashMap::new();
ht.insert("foo", 1);
ht.insert("bar", 2);
ht.insert("baz", 3);
ht.insert("oops", 4);
println!("{:?}", ht);
println!("{}", ht.contains_key("baz"));
println!("{}", ht.contains_key("Baz"));
println!("{:?}", ht.get("foo"));
println!("{:?}", ht.get("Foo"));
println!("{:?}", ht.remove("Oops"));
println!("{:?}", ht.remove("oops"));
println!("{:?}", ht.insert("foo", 100));
println!("{:?}", ht.insert("oops", 200));
for (k, v) in ht.iter() {
println!("{}, {}", k, v);
}
}
{"oops": 4, "bar": 2, "foo": 1, "baz": 3}
true
false
Some(1)
None
None
Some(4)
Some(1)
None
oops, 200
bar, 2
foo, 100
baz, 3
リスト : HashSet の簡単な使用例
use std::collections::HashSet;
fn main() {
let a: HashSet<_> = [1,2,3,4].iter().cloned().collect();
let b: HashSet<_> = [3,4,5,6].iter().cloned().collect();
println!("{:?}", a);
println!("{:?}", b);
println!("{}", a.contains(&1));
println!("{}", b.contains(&1));
let c: HashSet<_> = a.union(&b).cloned().collect();
println!("{:?}", c);
let d: HashSet<_> = a.intersection(&b).collect();
println!("{:?}", d);
let e: HashSet<_> = a.difference(&b).collect();
println!("{:?}", e);
println!("{}", a.is_subset(&c));
println!("{}", b.is_subset(&c));
println!("{}", a.is_subset(&b));
}
{1, 2, 3, 4}
{4, 6, 3, 5}
true
false
{4, 5, 3, 6, 2, 1}
{3, 4}
{1, 2}
true
true
false
リスト : Option の簡単な使用例
fn main() {
let mut a: Option<i32> = Some(100);
let mut b: Option<i32> = None;
println!("{}", a.is_some());
println!("{}", b.is_none());
{
let c = a.as_mut().unwrap();
*c = 200;
}
{
let d = a.as_ref().unwrap();
println!("{}", d);
}
let e = a.take();
println!("{:?}", a);
println!("{:?}", e);
let f = b.take();
println!("{:?}", b);
println!("{:?}", f);
let g = e.map(|v| v * v);
println!("{:?}", e);
println!("{:?}", g);
}
true true 200 None Some(200) None None Some(200) Some(40000)
リスト : AsRef トレイト
pub trait AsRef<T> where T: ?Sized
{
fn as_ref(&self) -> &T;
}
リスト : AsMut トレイト
pub trait AsMut<T> where T: ?Sized
{
fn as_mut(&mut self) -> &mut T;
}
リスト : 簡単な使用例
struct Foo<T> {
item: T
}
impl<T> AsRef<T> for Foo<T> {
fn as_ref(&self) -> &T {
&self.item
}
}
impl<T> AsMut<T> for Foo<T> {
fn as_mut(&mut self) -> &mut T {
&mut self.item
}
}
fn get<T: AsRef<i32>>(n: &T) -> &i32 {
n.as_ref()
}
fn inc<T: AsMut<i32>>(n: &mut T, m: i32) {
*n.as_mut() += m;
}
fn main() {
let mut a = Foo { item: 100 };
println!("{}", get(&a));
inc(&mut a, 100);
println!("{}", get(&a));
}
100 200
リスト : Borrow トレイト
pub trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
リスト : HashMap のメソッド contains_key() の仕様
fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where K: Borrow<Q>,
Q: Hash + Eq
リスト : Borrow の簡単な使用例
use std::borrow::Borrow;
use std::collections::HashMap;
#[derive(Hash, Eq, PartialEq)]
struct Foo {
num: i32
}
impl Borrow<i32> for Foo {
fn borrow(&self) -> &i32 {
&self.num
}
}
fn main() {
let mut ht: HashMap<Foo, i32> = HashMap::new();
ht.insert(Foo { num: 1 }, 100);
ht.insert(Foo { num: 2 }, 200);
ht.insert(Foo { num: 3 }, 300);
println!("{:?}", ht.get(&1));
println!("{:?}", ht.get(&4));
println!("{:?}", ht.get(&Foo { num: 2 }));
println!("{:?}", ht.get(&Foo { num: 5 }));
}
Some(100) None Some(200) None
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
リスト : スレッドの簡単な使用例 (1)
use std::{thread, time};
fn foo(msg: &str, n: u64) {
let m = time::Duration::from_millis(n);
for _ in 1 .. 10 {
println!("{}", msg);
thread::sleep(m);
}
}
fn main() {
let t1 = thread::spawn(|| {
foo("oops", 500);
});
let t2 = thread::spawn(|| {
foo("piyopiyo", 400);
});
println!("{:?}", t1.join().unwrap());
println!("{:?}", t2.join().unwrap());
}
oops piyopiyo piyopiyo oops piyopiyo oops piyopiyo oops piyopiyo piyopiyo oops piyopiyo oops piyopiyo oops piyopiyo oops oops () ()
リスト : スレッドの簡単な使用例 (2)
use std::thread;
use std::time::Instant;
// フィボナッチ数列
fn fibo(n: i64) -> i64 {
if n < 2 {
n
} else {
fibo(n - 1) + fibo(n - 2)
}
}
fn main() {
let s1 = Instant::now();
println!("{}", fibo(40));
let e1 = s1.elapsed();
println!("{}.{:03}秒経過しました。", e1.as_secs(), e1.subsec_nanos() / 1_000_000);
let s2 = Instant::now();
let mut buff: Vec<_> = vec![];
buff.push(thread::spawn(|| fibo(40)));
buff.push(thread::spawn(|| fibo(40)));
for x in buff {
println!("{}", x.join().unwrap());
}
let e2 = s2.elapsed();
println!("{}.{:03}秒経過しました。", e2.as_secs(), e2.subsec_nanos() / 1_000_000);
}
$ rustc -O sample61.rs $ ./sample61 102334155 0.372秒経過しました。 102334155 102334155 0.407秒経過しました。
pub fn channel<T>() -> (Sender<T>, Receiver<T>)
fn send(&self, t: T) -> Result<(), SendError<T>> fn recv(&self) -> Result<T, RecvError>
リスト : チャネルの簡単な使用例
use std::thread;
use std::sync::mpsc;
fn fibo(n: i64) -> i64 {
if n < 2 {
n
} else {
fibo(n - 1) + fibo(n - 2)
}
}
fn main() {
let (tx, rx) = mpsc::channel();
for x in vec![40, 39, 38, 37] {
let tx = tx.clone();
thread::spawn(move || tx.send(fibo(x)).unwrap());
}
for _ in 0 .. 4 {
println!("{}", rx.recv().unwrap());
}
}
24157817 39088169 63245986 102334155
fn lock(&self) -> LockResult<MutexGuard<T>>
リスト : Arc と Mutex の簡単な使用例
use std::thread;
use std::sync::{Arc, Mutex};
fn main() {
let data = Arc::new(vec![10, 20, 30, 40]);
for i in 0 .. 4 {
let data = data.clone();
thread::spawn(move || {
println!("{}", data[i]);
}).join().unwrap();
}
let data1 = Arc::new(Mutex::new(vec![1, 2, 3, 4]));
for i in 0 .. 4 {
let data1 = data1.clone();
thread::spawn(move || {
let mut buff = data1.lock().unwrap();
buff[i] += 10;
println!("{}", buff[i]);
}).join().unwrap();
}
println!("{:?}", data1);
}
10
20
30
40
11
12
13
14
Mutex { data: [11, 12, 13, 14], poisoned: false, .. }
fn read(&self) -> LockResult<RwLockReadGuard<T>> fn write(&self) -> LockResult<RwLockWriteGuard<T>>
リスト : RwLock の簡単な使用例 (1)
use std::sync::RwLock;
fn main() {
let lock = RwLock::new(123);
{
let r1 = lock.read().unwrap();
let r2 = lock.read().unwrap();
println!("{}, {}", *r1, *r2);
//let mut w1 = lock.write().unwrap(); ブロックされる
//*w1 = 456;
//println!("{}", *w1);
}
{
let mut w1 = lock.write().unwrap();
*w1 = 456;
println!("{}", *w1);
//let mut w2 = lock.write().unwrap(); ブロックされる
//*w2 = 789;
//println!("{}", *w2);
//let r3 = lock.read().unwrap(); ブロックされる
//println!("{}", *r3);
}
}
123, 123 456
リスト : RwLock の簡単な使用例 (2)
use std::{thread, time};
use std::sync::{Arc, RwLock};
fn main() {
let lock = Arc::new(RwLock::new(1));
let t1;
let t2;
{
let lock = lock.clone();
t1 = thread::spawn(move || {
for _ in 0 .. 10 {
match lock.try_read() {
Ok(r) => println!("read data {}", *r),
_ => println!("Can't read data")
}
thread::sleep(time::Duration::from_millis(500));
}
});
}
{
let lock = lock.clone();
t2 = thread::spawn(move || {
for _ in 0 .. 10 {
match lock.try_write() {
Ok(mut w) => {
*w+= 1;
println!("write data {}", *w);
}
_ => println!("Can't write data")
}
thread::sleep(time::Duration::from_millis(500));
}
});
}
t1.join().unwrap();
t2.join().unwrap();
}
read data 1 write data 2 read data 2 Can't write data read data 2 Can't write data read data 2 Can't write data read data 2 Can't write data write data 3 Can't read data read data 3 Can't write data read data 3 Can't write data read data 3 Can't write data read data 3 Can't write data
read data 1 Can't write data write data 2 read data 2 write data 3 read data 3 write data 4 read data 4 write data 5 read data 5 write data 6 read data 6 write data 7 read data 7 write data 8 read data 8 write data 9 read data 9 write data 10 read data 10