LoginSignup
0
0

筆者が、Rust By Exampleを写経したり、Activityを実行したりした記録です

この記事のソースコード、記載は正しいかわかりませんし、効率的かどうかもわかりません
ご参考まで

Testcase: List

?をつけて、write!マクロ出力を継続させるということか?

write!(f, "{}", value)?;

ソースコード

use std::fmt;

struct List(Vec<i32>);

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let vec = &self.0;

        write!(f, "[")?;

        for (count, v) in vec.iter().enumerate() {
            if count != 0 { write!(f, ", ")?; }
            write!(f, "{}:{}", v,count)?;
        }

        write!(f, "]")
    }
}

fn main() {
    let v = List(vec![1, 2, 3]);
    println!("{}", v);
}

出力結果

[1:0, 2:1, 3:2]

Try

いちばん最初のwrite!?を削除すると、エラーとなる

- write!(f, "[")?;
+ write!(f, "[");

最初のwrite!で出力が終わってしまうことが原因かな?

   Compiling testcase_list v0.1.0 (E:\github\rust_example\testcase_list)
warning: unused `Result` that must be used
 --> src\main.rs:9:9
  |
9 |         write!(f, "[");
  |         ^^^^^^^^^^^^^^
  |
  = note: this `Result` may be an `Err` variant, which should be handled
  = note: `#[warn(unused_must_use)]` on by default
  = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)

Formatting

各種Formattingの練習です
前述の?も併用しました

右寄せとか0詰めとかも、まだ書き方に慣れていないため、これは繰り返し練習する

ソースコード

ソースコード
use std::fmt::{self, Formatter, Display};

#[derive(Debug)]
struct City {
    name: &'static str,
    lat: f32,   // Latitude
    lon: f32,   // Longitude
}

impl Display for City {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' };
        let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' };

        write!(f, "{:>10}: {:.3}°{} {:.3}°{}",
            self.name, self.lat.abs(), lat_c, self.lon.abs(), lon_c)
    }
}

#[derive(Debug)]
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

impl Display for Color {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "RGB({:>3}, {:>3}, {:>3}) ", self.red, self.green, self.blue)?;
        write!(f, "0x")?;
        write!(f, "{:02x}", self.red)?;
        write!(f, "{:02x}", self.green)?;
        write!(f, "{:02x}", self.blue)
    }
}

fn main() {
    let cities = [
        City { name: "Dublin", lat: 53.347778, lon: -6.259722 },
        City { name: "Oslo", lat: 59.95, lon: 10.75 },
        City { name: "Vancouver", lat: 49.25, lon: -123.1 },
    ];

    for city in &cities {
        println!("{}", city);
    }

    for city in &cities {
        println!("{:?}", city);
    }

    let colors = [
        Color { red: 128, green: 255, blue: 90 },
        Color { red: 0, green: 3, blue: 254 },
        Color { red: 0, green: 0, blue: 0 },
    ];

    for color in &colors  {
        println!("{}", color);
    }

    for color in &colors  {
        println!("{:?}", color);
    }
}

出力結果

    Dublin: 53.348°N 6.260°W
      Oslo: 59.950°N 10.750°E
 Vancouver: 49.250°N 123.100°W
City { name: "Dublin", lat: 53.34778, lon: -6.259722 }
City { name: "Oslo", lat: 59.95, lon: 10.75 }
City { name: "Vancouver", lat: 49.25, lon: -123.1 }
RGB(128, 255,  90) 0x80ff5a
RGB(  0,   3, 254) 0x0003fe
RGB(  0,   0,   0) 0x000000
Color { red: 128, green: 255, blue: 90 }
Color { red: 0, green: 3, blue: 254 }
Color { red: 0, green: 0, blue: 0 }

Premitives

primitives: 基本データ型
type annotate: 型指定

integersのデフォルト型はi32、floatsはf64

ソースコード

ソースコード
fn main() {
    let logical: bool = true;
    println!("{}", logical);

    let a_float: f64 = 1.0;
    let an_integer = 5i32;
    println!("{}", a_float);
    println!("{}", an_integer);

    let default_float = 3.0;
    let default_integer = 7;
    println!("{}", default_float);
    println!("{}", default_integer);

    let mut inferred_type = 12;
    println!("{}", inferred_type);
    inferred_type = 4294967296i64;
    println!("{}", inferred_type);

    let mut mutable = 12;
    println!("{}", mutable);
    mutable = 21;
    println!("{}", mutable);
    //mutable = true;

    let mutable = true;
    println!("{}", mutable);
}

出力結果

true
1
5
3
7
12
4294967296
12
21
true

Literals and operators

ソースコード

ソースコード
fn main() {
    println!("1 + 2 = {}", 1u32 + 2);
    //println!("1 - 2 = {}", 1u32 - 2);
    println!("1 - 2 = {}", 1i32 - 2);

    println!("1e4 is {}, -2.5e-3 is {}", 1e4, -2.5e-3);

    // 論理演算
    println!("true AND false is {}", true && false);
    println!("true OR false is {}", true || false);
    println!("NOT true is {}", !true);

    // Bit演算
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    println!("1 << 5 is {}", 1u32 << 5);
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);
    println!("0b{:08b} >> 2 is 0b{:08b}", 0x80u32, 0x80u32 >> 2);

    println!("One million is written as {}", 1_000_000u32);
}

出力結果

1 + 2 = 3
1 - 2 = -1
1e4 is 10000, -2.5e-3 is -0.0025
true AND false is false
true OR false is true
NOT true is false
0011 AND 0101 is 0001
0011 OR 0101 is 0111
0011 XOR 0101 is 0110
1 << 5 is 32
0x80 >> 2 is 0x20
0b10000000 >> 2 is 0b00100000
One million is written as 1000000

Try

overflowを起こす計算のうち、あらかじめ判明しているものはエラーとなる

-    println!("1 - 2 = {}", 1i32 - 2);
+    println!("1 - 2 = {}", 1u32 - 2);
error: this arithmetic operation will overflow
 --> src\main.rs:3:28
  |
3 |     println!("1 - 2 = {}", 1u32 - 2);
  |                            ^^^^^^^^ attempt to compute `1_u32 - 2_u32`, which would overflow
  |
  = note: `#[deny(arithmetic_overflow)]` on by default

Tuples

12個より要素が多いタプルはデバッグプリントできない
要素が1個のタプルをつくれるが、,が必要

ソースコード

ソースコード
use std::fmt;

fn reverse(pair: (i32, bool)) -> (bool, i32) {
    let (int_parm, bool_parm) = pair;

    (bool_parm, int_parm)
}

fn transpose(matrix: Matrix) -> Matrix {
    Matrix(matrix.0, matrix.2, matrix.1, matrix.3)
}

#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);

impl fmt::Display for Matrix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "( {} {} )", self.0, self.1)?;
        writeln!(f, "( {} {} )", self.2, self.3)
    }
}

fn main() {
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                    -1i8, -2i16, -3i32, -4i64,
                    0.1f32, 0.2f64,
                    'a', true);
    
    println!("Long tuple first value: {}", long_tuple.0);
    println!("Long tuple second value: {}", long_tuple.1);

    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    println!("tuple of tuples: {:?}", tuple_of_tuples);
    
    //let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
    //println!("Too long tuple: {:?}", too_long_tuple);

    let pair = (1, true);
    println!("Pair is {:?}", pair);

    println!("The reversed pair is {:?}", reverse(pair));

    println!("One element tuple: {:?}", (5u32,));
    println!("Just an integer: {:?}", (5u32));

    let tuple = (1, "hello", 4.5, true);
    let (a, b, c, d) = tuple;
    println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);

    let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
    println!("{:?}", matrix);
    println!("{}", matrix);

    println!("Matrix:\n{}", matrix);
    println!("Transpose:\n{}", transpose(matrix));
}

出力結果

Long tuple first value: 1
Long tuple second value: 2
tuple of tuples: ((1, 2, 2), (4, -1), -2)
Pair is (1, true)
The reversed pair is (true, 1)
One element tuple: (5,)
Just an integer: 5
1, "hello", 4.5, true
Matrix(1.1, 1.2, 2.1, 2.2)
( 1.1 1.2 )
( 2.1 2.2 )

Matrix:
( 1.1 1.2 )
( 2.1 2.2 )

Transpose:
( 1.1 2.1 )
( 1.2 2.2 )

Arrays and Slices

Arraysは同じ型のコレクションで、連続したメモリに配置される
arraysの長さはコンパイル時に既知、slicesの長さはコンパイル時に不定

ソースコード

ソースコード
use std::mem;

fn analyze_slice(slice: &[i32]) {
    println!("First element of the slice: {}", slice[0]);
    println!("The slice has {} elements", slice.len());
}

fn main() {
    let xs: [i32; 5] = [1, 2, 3, 4, 5];
    let ys: [i32; 500] = [0; 500];

    println!("First element of the array: {}", xs[0]);
    println!("Second element of the array: {}", xs[1]);

    println!("Number of elements in array: {}", xs.len());

    println!("Array occupies {} bytes", mem::size_of_val(&xs));

    println!("Borrow the whole array as a slice.");
    analyze_slice(&xs);

    println!("Borrow a section of the array as a slice.");
    analyze_slice(&ys[1..4]);

    let empty_array: [u32; 0] = [];
    assert_eq!(&empty_array, &[]);
    assert_eq!(&empty_array, &[][..]);

    for i in 0..xs.len() + 1 { // Oops, one element too far!
        match xs.get(i) {
            Some(xval) => println!("{}: {}", i, xval),
            None => println!("Slow down! {} is too far!", i),
        }
    }
    
    //println!("{}", xs[5]); // compile error
    //println!("{}", xs[..][5]); // runtime error
}

出力結果

First element of the array: 1
Second element of the array: 2
Number of elements in array: 5
Array occupies 20 bytes
Borrow the whole array as a slice.
First element of the slice: 1
The slice has 5 elements
Borrow a section of the array as a slice.
First element of the slice: 0
The slice has 3 elements
0: 1
1: 2
2: 3
3: 4
4: 5
Slow down! 5 is too far!

Try

コンパイルエラーになる場合

println!("{}", xs[5]); // compile error
   Compiling arrays_and_slices v0.1.0 (E:\github\rust_example\arrays_and_slices)
error: this operation will panic at runtime
  --> src\main.rs:36:20
   |
36 |     println!("{}", xs[5]); // compile error
   |                    ^^^^^ index out of bounds: the length is 5 but the index is 5   
   |
   = note: `#[deny(unconditional_panic)]` on by default

error: could not compile `arrays_and_slices` (bin "arrays_and_slices") due to 1 previous error

ランタイムエラーになる場合

println!("{}", xs[..][5]); // runtime error
thread 'main' panicked at src\main.rs:37:20:
index out of bounds: the len is 5 but the index is 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\arrays_and_slices.exe` (exit code: 101)

Structures

3つのタイプのStructuresがある

  • タプル構造体、一般的にはタプル
  • 古典的なC言語的な構造体
  • ユニット、フィールドを持たない、ジェネリックスな使用用途

ソースコード

ソースコード
#![allow(dead_code)]

use std::fmt;

#[derive(Debug)]
struct Person {
    name: String,
    age: u8,
}

struct Unit;

struct Pair(i32, f32);

struct Point {
    x: f32,
    y: f32,
}

struct Rectangle {
    top_left: Point,
    bottom_right: Point,
}

fn rect_area(rect: Rectangle) -> f32 {
    let Rectangle {
            top_left: Point {x: p1_x, y: p1_y },
            bottom_right: Point {x: p2_x, y: p2_y }
        } = rect;

    let height = if p1_y > p2_y {p1_y - p2_y} else {p2_y - p1_y};
    let width = if p1_x > p2_x {p1_x - p2_x} else {p2_x - p1_x};

    height * width
}

fn square(p: Point, f: f32) -> Rectangle {
    Rectangle {
        top_left: Point { x: p.x, y: p.y },
        bottom_right: Point { x: p.x + f, y: p.y + f }
    }
}

impl fmt::Display for Rectangle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "P1({}, {}), P2({}, {})",
            self.top_left.x,
            self.top_left.y,
            self.bottom_right.x,
            self.bottom_right.y,
        )
    }
}

fn main() {
    let name = String::from("Peter");
    let age = 25;
    let peter = Person { name, age };

    println!("{:?}", peter);

    let point: Point = Point { x: 10.0, y: 10.0 };
    let another_point: Point = Point { x: 15.0, y: 15.0 };

    println!("point coordinates: ({}, {})", point.x, point.y);

    let bottom_right = Point { x: 4.0, ..another_point };

    println!("second point: ({}, {})", bottom_right.x, bottom_right.y);

    let Point {x: left_edge, y: top_edge } = point;

    let rectangle = Rectangle {
        top_left: Point { x: left_edge, y: top_edge },
        bottom_right: bottom_right,
    };

    let _unit = Unit;

    let pair = Pair(1, 0.1);

    println!("pair contains {:?} and {:?}", pair.0, pair.1);

    let Pair(integer, decimal) = pair;

    println!("pair contains {:?} and {:?}", integer, decimal);

    println!("Rectangle is {}", rectangle);
    println!("Rectangle area is {}", rect_area(rectangle));

    let square_info = square(point, 10.0); 

    println!("Square is {}", square_info);
    println!("Square area is {}", rect_area(square_info));
}

出力結果

Person { name: "Peter", age: 25 }
point coordinates: (10, 10)
second point: (4, 15)
pair contains 1 and 0.1
pair contains 1 and 0.1
Rectangle is P1(10, 10), P2(4, 15)
Rectangle area is 30
Square is P1(10, 10), P2(20, 20)
Square area is 100

後書き

ディスプレイ用の処理の書き方がなかなか覚えられないため、要反復練習

型がきちきちに決まっていて、その通りにしか書けないため、コーディングしやすい印象でした

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0