[rustの学習開始時期]
2020/02/10


[LinuxMINTへのインストール方法]
curl https://sh.rustup.rs -sSf | sh
または
sudo apt install rustc
sudo apt install cargo

(注）
    WSLへのインストールは
    sudo apt install rustc
    sudo apt install cargo
    で行わないとエラーになる。
    また、rust実行時は 管理者権限(sudo)で行うこと

アンインストール方法
sudo /usr/local/lib/rustlib/uninstall.sh
または
sudo apt uninstall ...
または
rustup self uninstall

アップデート方法
    rustup update
    を実行する。

[Windowsへのインストール方法]
まず、Microsoft Visual Studio 2019 をインストールする。
https://news.mynavi.jp/article/rust-4/ 参照

そして、
https://win.rustup.rs
から
rustup-init.exe をダウンロードして実行する。


[ソースコードとコンパイル方法]
ソースコードのファイル名には、 .rs の拡張子をつける。

コンパイルコマンド
rustc


[cargo build]
Cargo.toml の位置
    projects/hellow_world/src
                         /target        このフォルダーは cargo build で自動的に作成される
                         Cargo.toml     C は必ず大文字

ソースコード
    /mnt/datadisk/USB_DATA/rust/projects/hello_world/src/main.rs
    内容
    fn main(){
        println!("俺は山田だ");
    }

Cargo.toml の内容
    [package]

    name = "hello_world"
    version = "0.0.1"
    authors = [ "dangoyadanhe" ]

cargo build を実行するとできる実行形式のファイル
    projects/hello_world/target/debug/hello_world

Cargo を作成し、同時にコンパイルして実行するコマンド
tadaaki30@ta53que30:/mnt/datadisk/USB_DATA/rust/projects/hello_world$ cargo run
   Compiling hello_world v0.0.1 (/mnt/datadisk/USB_DATA/rust/projects/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.29s
     Running `target/debug/hello_world`
俺は山田だ

Cargoの作成
$ cd ~/projects
$ cargo new guessing_game --bin
$ cd guessing_game
この結果、Cargo.tomlが作成される。


[hellow_world]
fn main() {
    println!("Hello, world!");
}


[プレリュード prelude]
use std::io;

ユーザの入力を取得して結果を出力する必要があります。 なので io 標準ライブラリから
ライブラリが必要になります。 Rustが全てのプログラムにデフォルトで読み込むものは
少しだけで、「プレリュード」といいます。 プレリュードになければ、直接 use しなければ
いけません。 2つめの「プレリュード」、io プレリュードもあり、同様にそれをインポート
すると io に関連した多数の有用なものがインポートされます。

Rustの標準ライブラリにはさまざまなものが付属しています。 ただし、使用したものを
すべて手動でインポートする必要がある場合、非常に冗長になります。 
しかし、プログラムが決して使用しない多くのものをインポートすることも良くありません。
バランスをとる必要があります。

プレリュードは、RustがすべてのRustプログラムに自動的にインポートするもののリストです。
それは可能な限り小さく保たれ、ほとんどすべてのRustプログラムで使用されるもの、
特に特徴に焦点を当てています。
技術レベルでは、Rustが挿入します

    extern crate std ; 
    すべてのクレートのクレートルートに
    std :: prelude :: v1 :: *を使用します。 

その他のプレリュード

プレリュードは、複数のタイプをより便利に使用するためのパターンとして見ることができます。
そのため、標準ライブラリにはstd::io::preludeなどの他のプレリュードがあります。
Rustエコシステムのさまざまなライブラリも独自のプレリュードを定義できます。

「プレリュード」とこれらの他のプレリュードの違いは、「プレリュード」は自動的に「d」を
useせず、手動でインポートする必要があることです。 これは、すべての構成コンポーネントを
インポートするよりも簡単です。

プレリュードの内容
プレリュードの現在のバージョン（バージョン1）はstd::prelude::v1にあり、以下を
再エクスポートします。

    std::marker :: { Copy 、 Send 、 Sized 、 Sync }。 マーカー特性は、タイプの
        基本的なプロパティを示します。
    std::ops :: { Drop 、 Fn 、 FnMut 、 FnOnce }。 destuctorとoverloading ()両方の
        さまざまな操作。
    std::mem :: drop 、値を明示的に削除するための便利な関数。
    std::boxed :: Box 、ヒープに値を割り当てる方法。
    std::borrow ToOwned :: ToOwned 、 to_owned()を定義する変換特性、借用型から
        所有型を作成するための汎用メソッド。
    std::clone :: Cloneは、 clone()を定義するユビキタスな特性であり、値のコピーを
        生成するメソッドです。
    std::cmp :: { PartialEq 、 PartialOrd 、 Eq 、 Ord }。 比較特性は、比較演算子を
        実装し、多くの場合特性境界で見られます。
    std::convert :: { AsRef 、 AsMut 、 Into 、 From }。
        精通したAPI作成者がオーバーロードメソッドを作成するために使用する一般的な変換。
    std::default :: Default 、デフォルト値を持つタイプ。
    std::iter :: { Iterator 、 Extend 、 IntoIterator 、 DoubleEndedIterator 、 
        ExactSizeIterator }。 さまざまな種類の反復子。
    std::option :: Option :: { self 、 Some 、 None }。 値の有無を表すタイプ。
        このタイプは非常によく使用され、そのバリアントもエクスポートされます。
    std::result :: Result :: { self 、 Ok 、 Err }。 成功または失敗する可能性のある
        関数のタイプ。 Optionと同様に、そのバリアントもエクスポートされます。
    std::slice :: SliceConcatExtは、技術的な理由で存在するが、存在する必要はない
        特性です。 スライスに関するいくつかの便利なメソッドを提供します。
    std::string :: { String 、 ToString }、ヒープに割り当てられた文字列。
    std::vec :: Vecは、成長可能なヒープに割り当てられたベクトルです。 


[クレートとは]
クレートとはRustのコードのパッケージです。
今まで作ってきたのは実行可能な「バイナリクレート」です。 rand は「ライブラリクレート」で、
他のプログラムから使われることを意図したコードが入っています。

クレートの入手方法
https://crates.io/crates/クレート名
で、クレート名を入力する。


[fn main()]
main() 関数がプログラムのエントリポイントになります。 fn 構文で新たな関数を宣言し、
() が引数がないことを示し、 { が関数の本体部の始まりです。 返り値の型は書いていない
ので () 、空のタプルとして扱われます。
    println!("Guess the number!");
    println!("Please input your guess.");


[let文 ミュータブル、イミュータブル]
let文は「変数束縛」を作る。
    let foo = bar;
これは foo という名前の束縛を作り、それを値 bar に束縛します。 多くの言語では
これは「変数」と呼ばれるものですが、Rustの変数束縛は少しばかり皮を被せてあります。
例えば、束縛はデフォルトでイミュータブル (不変)です。 なので、この例ではイミュータブル
ではなくミュータブル(可変)な束縛にするために mut を使っているのです。 
let は代入の左辺に名前を取る訳ではなくて実際にはパターンを受け取ります。
    let foo = 5; // イミュータブル
    let mut bar = 5; // ミュータブル


[::new() 構文 ダブルコロン 二重コロン]
let mut guess = String::new();
    ::new() 構文は特定の型の「関連関数」なので :: 構文を使っています。 
    つまり、これは String のインスタンスではなく String 自体に関連付けられている
    ということです。 これを「スタティックメソッド」と呼ぶ言語もあります。
    この関数は新たな空の String を作るので new() と名付けられています。
    new() 関数はある種の新たな値を作るのによく使われる名前なので様々な型でこの関数を
    見るでしょう。

let s = String::from("hello");
    この二重コロンは、string_fromなどの名前を使うのではなく、 String型直下のfrom関数を
    特定する働きをする演算子です。
    この型はヒープにメモリを確保するので、 コンパイル時にはサイズが不明なテキストも
    保持することができるのです。
    from関数を使用して、 文字列リテラルからString型を生成できます。


[Struct std::io::Stdin]
    pub struct Stdin {
     //一部のフィールドが省略されました
    }
プロセスの標準入力ストリームへのハンドル。

各ハンドルは、このプロセスへの入力データのグローバルバッファへの共有参照です。
ハンドルをlockして、 BufReadメソッド（例： .lines() ）に完全にアクセスできます。 
それ以外の場合、このハンドルへの書き込みは、他の書き込みに関してロックされます。

このハンドルはRead特性を実装しますが、 Stdin同時読み取りは注意して実行する必要が
あることに注意してください。

関数io::stdin()によって作成されます。 


[println!]
    println!("You guessed: {}", guess);
これは入力を保持している文字列を印字します。 {} はプレースホルダで、引数として 
guess を渡しています。 複数の {} があれば、複数を引数を渡すことになります。

let x = 5;
let y = 10;

println!("x and y: {} and {}", x, y);


[dependencies]
Cargo.toml の [dependencies] (訳注: 依存)セクションは [package] セクションに
似ています。 後続の行は次のセクションが始まるまでそのセクションに属します。 
Cargoはどの外部クレートのどのバージョンに依存するのかの情報を取得するのに
dependenciesセクションを使います。 今回のケースではバージョン0.3.0を指定して
いますが、Cargoは指定されたバージョンと互換性のあるバージョンを理解します。 
Cargoはバージョン記述の標準、セマンティックバージョニングを理解します。 
上記のようなそのままのバージョンは ^0.3.0 の略記で、「0.3.0と互換性のあるもの」
という意味です。 正確に 0.3.0 だけを使いたいなら rand="=0.3.0" (等号が2つある
ことに注意して下さい)と書きます。 そして最新版を使いたいなら * を使います。
また、バージョンの範囲を使うことも出来ます。


[文字型変数を数字に変換する]
let mut guess = String::new();  // ここで変数 guess が文字列になっている
let guess: u32 = guess.trim().parse()
        .expect("Please type a number!");  
            //これで数字に変換（シャドーイング）することができる
        
別のやり方
let stri: String = String::from("5");
let num: i32 = stri.parse().unwrap();
println!("{}", num);  // 5


[コロン]
型はコロン(:)のあとに書きます。
let x: i32 = 5;

let s = String::from("hello");
この二重コロンは、string_fromなどの名前を使うのではなく、 String型直下のfrom
関数を特定する働きをする演算子です。

match guess.cmp(&secret_number) {
    Ordering::Less    => println!("Too small!"),
    Ordering::Greater => println!("Too big!"),
    Ordering::Equal   => println!("You win!"),
}

cmp() は比較可能なものに対しならなんでも呼べて、引数に比較したい対象の参照を取ります。 
cmp() は先程 use した Ordering を返します。 match文を使って正確に Ordering の
どれであるかを判断しています。 
Ordering はenum (訳注: 列挙型)で、enumは「enumeration(訳注: 列挙)」の略です。 
このようなものです。


[新しいプロジェクトを作成する]
cargo new NewProjectName --bin


[文字列を数値に変換する]
String → num

.parse().unwrap()を利用すると出来ます。
ちゃんと変換後の型を指定しないと動きません。

    let stri: String = String::from("5");
    let num: i32 = stri.parse().unwrap();
    println!("{}", num);  // 5


[コンソールにて文字列を入力し、結果をprintにて出力させる方法]
---- 数値を入力する場合 ---
use std::io;

fn main() {
    println!("0 〜 9 から1つ数値を選んで入力して下さい:");
    let answer01 = get_input();

    println!("再度、数値を入力して下さい:");
    let answer02 = get_input();

    match answer01 {
        1 => println!("ゲーム01を選択。プレイ時間は{}分です。", answer02),
        2 => {
            let num01 = 4;
            println!("ゲーム02を選択。 {} + {} = {}", num01
                                                , answer02
                                                , num01 + answer02);
        },
        3 => {
            print!("ゲーム03を選択。 ");
            println!("answer02 = {} です。", answer02);
        },
        _ => println!("終了します。"),
    }
}

fn get_input() -> i32 {
    let mut number = String::new();
    io::stdin().read_line(&mut number).ok();
    return number.trim().parse().ok().unwrap();
}

コンソールからの入力はあくまで文字なので、いずれ数値に置き換えるとしても、
まずはString型でミュータブル変数を作成する必要があります。
get_input() 関数にて、戻り値の型を i32 や usize 等にします。

--- 文字列を入力する場合 ---
use std::io;

fn main() {
    println!("何か文字を入力して下さい:");

    let answer = get_input();

    println!("{}", answer);
}

fn get_input() -> String {
    let mut word = String::new();
    io::stdin().read_line(&mut word).ok();
    return word.trim().to_string();
}
これを実行して、ENTERのみ入力すると
answer.len() = 0
となる


[基本データ型　変数の型]
Rustは様々な基本データ型(primitives)の使用をサポートしています。以下がその例です。

    符号付き整数: i8, i16, i32, i64, isize（ポインタのサイズ）
    符号無し整数: u8, u16, u32, u64, usize（ポインタのサイズ）
    浮動小数点: f32, f64
    char: 'a', 'α', '∞'などのUnicodeのスカラー
    bool: trueまたはfalse
    unit型: ()が唯一の値
    配列: e.g. [1, 2, 3]など
    タプル: e.g. (1, true)

変数は常に型指定(type annotate)可能です。数値型の場合はさらにサフィックスでの
指定が可能です。指定しない場合デフォルトになります。
例えば整数はi32が、浮動小数点はf64がデフォルトです。


[演算子]
演算子  例                                          説明                                オーバーロードできる？
------  --------------------------------------      ----------------------------------- ----------------------
!       ident!(...), ident!{...}, ident![...]       マクロ展開  
!       !expr                                       ビット反転、または論理反転          Not
!=      var != expr                                 非等価比較                          PartialEq
%       expr % expr                                 余り演算                            Rem
%=      var %= expr                                 余り演算後に代入                    RemAssign
&       &expr, &mut expr                            借用    
&       &type, &mut type, &'a type, &'a mut type    借用されたポインタ型    
&       expr & expr                                 ビットAND                           BitAnd
&=      var &= expr                                 ビットAND後に代入                   BitAndAssign
&&      expr && expr                                論理AND 
*       expr * expr                                 掛け算                              Mul
*       *expr                                       参照外し    
*       *const type, *mut type                      生ポインタ  
*=      var *= expr                                 掛け算後に代入                      MulAssign
+       trait + trait, 'a + trait                   型制限の複合化  
+       expr + expr                                 足し算                              Add
+=      var += expr                                 足し算後に代入                      AddAssign
,       expr, expr                                  引数と要素の区別    
-       - expr                                      算術否定                            Neg
-       expr - expr                                 引き算                              Sub
-=      var -= expr                                 引き算後に代入                      SubAssign
->      fn(...) -> type, |...| -> type              関数とクロージャの戻り値型  
.       expr.ident                                  メンバーアクセス    
..      .., expr.., ..expr, expr..expr              未満範囲リテラル    
..      ..expr                                      構造体リテラル更新記法  
..      variant(x, ..), struct_type { x, .. }       「残り全部」パターン束縛    
...     expr...expr                                 パターンで: 以下範囲パターン    
/       expr / expr                                 割り算                              Div
/=      var /= expr                                 割り算後に代入                      DivAssign
:       pat: type, ident: type                      型制約  
:       ident: expr                                 構造体フィールド初期化子    
:       'a: loop {...}                              ループラベル    
;       expr;                                       文、要素終端子  
;       [...; len]                                  固定長配列記法の一部    
<<      expr << expr                                左シフト                            Shl
<<=     var <<= expr                                左シフト後に代入                    ShlAssign
<       expr < expr                                 未満比較                            PartialOrd
<=      expr <= expr                                以下比較                            PartialOrd
=       var = expr, ident = type                    代入/等価   
==      expr == expr                                等価比較    PartialEq
=>      pat => expr                                 matchアーム記法の一部   
>       expr > expr                                 より大きい比較                      PartialOrd
>=      expr >= expr                                以上比較                            PartialOrd
>>      expr >> expr                                右シフト                            Shr
>>=     var >>= expr                                右シフト後に代入                    ShrAssign
@       ident @ pat                                 パターン束縛    
^       expr ^ expr                                 ビットXOR                           BitXor
^=      var ^= expr                                 ビットXOR後に代入                   BitXorAssign
|       pat | pat                                   パターンOR  
|       |…| expr                                   クロージャ  
|       expr | expr                                 ビットOR                            BitOr
|=      var |= expr                                 ビットOR後に代入                    BitOrAssign
||      expr || expr                                論理OR  
?       expr?                                       エラー委譲  


[トレイト]
トレイトは、ある型の機能を表現します。トレイトを使うことで同じ名前の機能をあらゆる型に
対して実装したり、追加することができます。トレイトはインタフェースや抽象基底クラスと
いった概念に似ており、ポリモーフィズム(多様性)を実現します。
トレイトの定義と実装

まず、トレイトの定義方法と型への実装方法を説明します。
トレイトの定義はtraitブロックで行います。

trait Trait {
    fn method(...);
    ...
}

traitブロックにはメソッドを列挙していきます。このとき、メソッドの機能はまだ、
定義しません(後述するデフォルトメソッドは例外)。
例えば以下のように定義します。

mod mod_traits {
    pub trait Out {
        fn print_twice(&self);
        fn print_add_doller(&self);
    }
}

上記はOutというトレイトをパブリックで定義しています。Outはメソッドを2つ持ちます。
なお、modブロックで囲っているのはモジュールとして別ファイルで定義した想定で
進めたかったからです。
ある型にトレイトを使って実装するにはimplブロックを使います。

impl Trait for Type {
    fn method(...) {
        ...
    }
}

この時に型Typeに対してTraitのmethodを実装していきます。
先ほどのOutトレイトを実装してみます。

use mod_traits::Out;

#[derive(Debug)]
struct Number {
    num: i32
}

impl Out for Number {
    fn print_twice(&self) {
        println!("{}, {}", self.num, self.num);
    }

    fn print_add_doller(&self) {
        println!("$ {}", self.num);
    }
}

impl Out for String {
    fn print_twice(&self) {
        println!("{}, {}", self, self);
    }

    fn print_add_doller(&self) {
        println!("$ {}", self);
    }
}

まず、重要なのはそのトレイトがスコープ内に存在しないと使えないということです。
なので、最初にuseを使ってインポートしています。また、そのトレイトのメソッドを
使う際にもトレイトがスコープ内にいなければ使えません。
次に型となるNumber構造体を定義します。このNumber構造体にOutトレイトを実装します。
そして、Outトレイトのメソッドの動作も定義していきます。
ついでに、Stringに対してもOutトレイトを実装しました。こうすれば、既存の型に対して
メソッドを追加することができます。

使い方は単純にメソッドを呼ぶように使えます。

fn main() {
    let num = Number {num: 5};
    num.print_twice();      // 5, 5
    num.print_add_doller(); // $ 5
    String::from("JUMP!").print_twice();          // JUMP!, JUMP!
    String::from("cargo run").print_add_doller(); // $ cargo run
}

トレイトには、多様性を実現するために2種類の方法があります。

    トレイトオブジェクト
    ジェネリクス


[インスタンス instance]
インスタンスとは、事実、事例、例、場合などの意味を持つ英単語。ソフトウェアの分野で、
あらかじめ定義されたコンピュータプログラムやデータ構造などを、メインメモリ上に展開して
処理・実行できる状態にしたものをインスタンスという。この意味では「実体」と訳されることもある。

特に、オブジェクト指向プログラミングで、クラス定義に基いてメモリ上にデータの集合として
展開されたオブジェクトのことをインスタンスという。
クラスは一種の雛形であるため、同じクラスから異なる内容を持った複数のインスタンスを
生成して扱うことができる。

仮想化の分野では、物理的な一台のコンピュータ上で、ソフトウェアとして実装された仮想的な
コンピュータを起動したものをインスタンス（VMインスタンス、仮想化インスタンス）ということがある。
利用者やOSなどから見るとあたかも一台のコンピュータが稼動しているかのように振る舞い、
実際のコンピュータと同じようにその上でソフトウェアを起動することができる。


[クラス class]
クラスとは、級、階級、等級、格、類、分類、種類、学級、科目、授業などの意味を持つ英単語。
ITの分野では、オブジェクト指向プログラミングにおけるオブジェクトの雛形の意味や、
何らかの階級や分類を表す名称の一部としてよく用いられる。

オブジェクト指向では、互いに関連するデータと、データを操作するメソッドを一つのオブジェクトと
呼ばれる単位に一体化（カプセル化）して取り扱う。あるオブジェクトがどのようなデータと
メソッドから作られるのかを定義した、言わば雛形にあたるものをクラスという。
プログラムの実行時にはクラスを元にメモリ空間上に具体的なオブジェクトが生成されるが、
この実体化されたオブジェクトのことを「インスタンス」（instance）という。

クラスには、オブジェクト内部で取り扱うデータ（フィールド/メンバ変数）の名称やデータ型・
データ構造、アクセス可能な範囲（クラス外から参照・操作可能か否かなど）を宣言し、また、
メソッド（メンバ関数）の名称や引数、処理内容の詳細、アクセス範囲を記述する。フィールドや
メソッドは通常はインスタンスに属するが、クラスそのものに属するものを宣言することができ、
それぞれ「クラス変数」（静的フィールド/静的メンバ変数）、「クラスメソッド」（静的メソッド）
などという。


[メソッド method]
① 目的を達成するために決められたやり方。方法。方式。
② オブジェクト指向プログラミングにおいて、オブジェクトに対する操作を定義した手続き。
　メソッドをオブジェクトの属するクラスに定義するプログラミング言語が多い。 → オブジェクト
　指向プログラミング


[スタティックメソッド static method スタティック変数]
PHP用語集から抜粋
クラス自体に一つだけ用意されているプロパティ（データ）、メソッド。

インスタンスを作らなくても(クラス名)::（プロパティ、またはメソッド名)で呼び出したり
アクセスすることができる。
通常のプロパティ、メソッドはインスタンスごとに用意されていて、インスタンスを作らないと
使用することはできない。

各インスタンス一つ一つに持たせる必要のないデータや、インスタンスごとのプロパティに
アクセスすることがないメソッドは、スタティック変数やスタティックメソッドとして定義した方がよい。

スタティック変数、スタティックメソッドを定義するときは、staticという言葉をつけて定義し、
クラス内からアクセスしたり呼び出す時はself::(変数名、メソッド名)とする。 


[レジストリ registry]
レジストリとは、Crates.ioのデータのコピーです。
Crates.ioとは、Rustのエコシステムにいる人間が、 他の人が使えるように自分の
オープンソースのRustプロジェクトを投稿する場所です。


[スレッド thread]
コンピュータが連続して実行する命令の列など、一筋の連続した流れになっているものを
比喩的に表す。


[シード値 seed]
乱数を作成するときの最初の設定値のことを シード値 と言います。
コンピュータで乱数を生成する場合、ある数値をシード値（seed→種）として用い、 
その値を基にして特定の演算により乱数を生成します。
このため、同じシード値を使用した場合、発生する単数（結果）は全く同じものになります。


[スコープ scope]
スコープ（Scope）は「範囲」の意味。プロジェクトの内容の範囲を定義したもの指す。
限られたリソースと期間内にプロジェクトの目的を達成するために、関係者全員と
共通認識をもってスコープを決定する。

プログラミングにおけるスコープ（英: scope, 可視範囲）とは、ある変数や関数などの
名前（識別子）を参照できる範囲のこと。通常、変数や関数が定義されたスコープの外側からは、
それらの名前を用いるだけでは参照できない。このときこれらの変数や関数は「スコープ外」
である、あるいは「見えない」といわれる。 

スコープとは、 要素が有効になるプログラム内の範囲のことです。


[キーワード]
以下のキーワードは、解説された通りの機能が現状あります。

    as - 基礎的なキャストの実行、要素を含む特定のトレイトの明確化、useやextern crate文の要素名を変更する
    break - 即座にループを抜ける
    const - 定数要素か定数の生ポインタを定義する
    continue - 次のループの繰り返しに継続する
    crate - 外部のクレートかマクロが定義されているクレートを表すマクロ変数をリンクする
    else - ifとif letフロー制御構文の規定
    enum - 列挙型を定義する
    extern - 外部のクレート、関数、変数をリンクする
    false - bool型のfalseリテラル
    fn - 関数か関数ポインタ型を定義する
    for - イテレータの要素を繰り返す、トレイトの実装、高階ライフタイムの指定
    if - 条件式の結果によって条件分岐
    impl - 固有の機能やトレイトの機能を実装する
    in - forループ記法の一部
    let - 変数を束縛する
    loop - 無条件にループする
    match - 値をパターンとマッチさせる
    mod - モジュールを定義する
    move - クロージャにキャプチャした変数全ての所有権を奪わせる
    mut - 参照、生ポインタ、パターン束縛で可変性に言及する
    pub - 構造体フィールド、implブロック、モジュールで公開性について言及する
    ref - 参照で束縛する
    return - 関数から帰る
    Self - トレイトを実装する型の型エイリアス
    self - メソッドの主題、または現在のモジュール
    static - グローバル変数、またはプログラム全体に渡るライフタイム
    struct - 構造体を定義する
    super - 現在のモジュールの親モジュール
    trait - トレイトを定義する
    true - bool型のtrueリテラル
    type - 型エイリアスか関連型を定義する
    unsafe - unsafeなコード、関数、トレイト、実装に言及する
    use - スコープにシンボルをインポートする
    where - 型を制限する節に言及する
    while - 式の結果に基づいて条件的にループする

将来的な使用のために予約されているキーワード

以下のキーワードには機能が何もないものの、将来的に使用される可能性があるので、Rustにより予約されています。

    abstract
    alignof
    become
    box
    do
    final
    macro
    offsetof
    override
    priv
    proc
    pure
    sizeof
    typeof
    unsized
    virtual
    yield


[定数 constants]
まず、定数にはmutキーワードは使えません: 定数は標準で不変であるだけでなく、
常に不変なのです。

定数はletキーワードの代わりに、constキーワードで宣言し、値の型は必ず注釈
しなければなりません。

定数はどんなスコープでも定義できます。グローバルスコープも含めてです。
なので、 いろんなところで使用される可能性のある値を定義するのに役に立ちます。

最後の違いは、定数は定数式にしかセットできないことです。関数呼び出し結果や、
実行時に評価される値にはセットできません。

Rustの定数の命名規則は、 全て大文字でアンダースコアで単語区切りすることです。
例
    const MAX_POINTS: u32 = 100_000;
    println!("MAX_POINTS = {}",MAX_POINTS);
    結果
    MAX_POINTS = 100000


[バリアント variant]
Variant型とは、Visual Basicなどで用いられる変数などのデータ型の一つで、
どのような型のデータでも格納できる特殊な型。代入時に処理系が値の型を調べ、
適合するデータ型が自動的に選択される。“variant”は「異なる」「多様な」などの
意味を持つ英単語。

Variant型の変数には文字列や整数など様々なプリミティブ型の値を代入する
ことができ、以降はその型の値として処理される。異なる型のデータを代入し直すと、
値の型に合わせて変数のデータ型も変更される。言語や処理系によっては
オブジェクトや配列、ユーザー定義型の値などを代入することもできる。

あらかじめどのようなデータ型を受け取るか分からない場合などに便利だが、
通常の型に比べ必要なメモリ領域が大きく、処理速度も余計にかかる。
また、内部的に型が異なる値同士の比較や演算でもエラーになるとは限らず、
意図しない挙動のまま実行が継続されることがあり、乱用はバグの温床になるとされる。


[はーとめのねこ ハート目の猫]
😻


[タプル型]

タプルは、複数の型の何らかの値を一つの複合型にまとめ上げる一般的な手段です。

タプルは、丸かっこの中にカンマ区切りの値リストを書くことで生成します。タプルの位置ごとに
型があり、 タプル内の値はそれぞれ全てが同じ型である必要はありません。
今回の例では、型注釈をあえて追加しました:

ファイル名: src/main.rs

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}

変数tupは、タプル全体に束縛されています。なぜなら、タプルは、一つの複合要素と考えられる
からです。 
タプルから個々の値を取り出すには、パターンマッチングを使用して分解することができます。
以下のように:

ファイル名: src/main.rs

fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!("The value of y is: {}", y);
}

このプログラムは、まずタプルを生成し、それを変数tupに束縛しています。 それからletと
パターンを使ってtup変数の中身を3つの個別の変数(x、y、zですね)に変換しています。 
この過程は、分配と呼ばれます。単独のタプルを破壊して三分割しているからです。
最後に、 プログラムはy変数の値を出力し、6.4と表示されます。

パターンマッチングを通しての分配の他にも、アクセスしたい値の番号をピリオド(.)に続けて
書くことで、 タプルの要素に直接アクセスすることもできます。例です:

ファイル名: src/main.rs

fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
}

このプログラムは、新しいタプルxを作成し、添え字アクセスで各要素に対して新しい変数も
作成しています。 
多くのプログラミング言語同様、タプルの最初の添え字は0です。

自作のサンプルプログラム
fn main(){
    let a0 = String::from("I am a boy");
    let a1 = String::from("You are a girl");
    
    println!("a0 = {}",a0);
    println!("a1 = {}",a1);
    
    let b = (a0,a1);
    println!("b0 = {}", b.0);
    println!("b1 = {}", b.1);
    
    let x: (String, String) = (String::from("山田の"), String::from("カカシ"));
    println!("x.0 = {}",x.0);
    println!("x.1 = {}",x.1);
}

実行結果
PS /mnt/datadisk/USB_DATA/rust/projects/trial> cargo run
   Compiling trial v0.1.0 (/mnt/datadisk/USB_DATA/rust/projects/trial)
    Finished dev [unoptimized + debuginfo] target(s) in 0.40s
     Running `target/debug/trial`
a0 = I am a boy
a1 = You are a girl
b0 = I am a boy
b1 = You are a girl
x.0 = 山田の
x.1 = カカシ


[関数 function]
fn main() {
    another_function(5, 6);
}

fn another_function(x: i32, y: i32) {
    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
}


[関数と変数の命名規則]
Rustの関数と変数の命名規則は、スネークケース(訳注: some_variableのような命名規則)を
使うのが慣例です。 スネークケースとは、全文字を小文字にし、単語区切りにアンダースコアを
使うことです。
fn main() {
    another_function(5, 6);
}

fn another_function(x: i32, y: i32) {
    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
}

fn another_function() {
    println!("Another function.");  // 別の関数
}
このfn another_function()の位置はmain.rsの前でも良い


[ステートメント statement]
ステートメントとは、発言、声明、宣言、供述、提示、報告書、明細書などの意味を持つ英単語。

コンピュータプログラムの構成単位となる、一つ一つの手続きや命令、宣言などのことを
ステートメントあるいは「文」という。
複数のステートメントを一つの文のように扱えるようまとめたものをブロックあるいは複文という。

どのようなステートメントを記述できるかはプログラミング言語の仕様によって決まっており、
プログラム中で使用する変数や定数、関数の名前やデータ型の宣言、関数の呼び出し、
オブジェクトの生成や破棄、変数への値の代入、条件分岐や繰り返し、何もしない（空文）などの
種類がある。


[文と式]
文とは、なんらかの動作をして値を返さない命令です。 式は結果値に評価されます。

fn main() {
    let x = 5;

    let y = {
        let x = 3;
        x + 1
    };

    println!("The value of y is: {}", y);
}

以下の式:

{
    let x = 3;
    x + 1
}

は今回の場合、4に評価されるブロックです。その値が、let文の一部としてyに束縛されます。 
今まで見かけてきた行と異なり、文末にセミコロンがついていないx + 1の行に気をつけてください。 
式は終端にセミコロンを含みません。式の終端にセミコロンを付けたら、文に変えてしまいます。
そして、文は値を返しません。 次に関数の戻り値や式を見ていく際にこのことを肝に銘じておいて
ください。


[ループ loop]
loopを使う場合
fn main() {
    loop {
        println!("again!");   // また
    }
}

whileで条件付きループ
fn main() {
    let mut number = 3;

    while number != 0 {
        println!("{}!", number);

        number = number - 1;
    }

    // 発射！
    println!("LIFTOFF!!!");
}

forでコレクションを覗き見る
fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a.iter() {
        // 値は{}です
        println!("the value is: {}", element);
    }
}
あるいは
fn main() {
    for number in (1..4).rev() {
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
}
よくある、 for (i = 0; i < 10; i++) のような形式は無く、 Range を
利用します。 Range は (1..4) のように表現し、 rev() で取り出すように
見受けられます。


[スタック stack]
スタックとは スタックとは，逐次入出力が繰り返されるデータを一時的に貯えるための
データ構造である。 

スタックとは、最も基本的なデータ構造の一つで、要素が入ってきた順に一列に並べ、
後に入れた要素から順に取り出すという規則で出し入れを行うもの。本や書類、箱などを
積み上げて置く（stack）ことになぞらえてこのように呼ばれる。

スタックは要素が入ってきた順に並べ、先頭が最も古く、末尾が最も新しい要素となる。
取り出すときは末尾にある最も新しいものから順に取り出す。

データを追加することは、 スタックにpushするといい、データを取り除くことは、スタックから
popすると表現します


[ヒープ heap]
ヒープとは、データ構造の一種で、木構造（ツリー構造）のうち、親要素が子要素より常に
大きい（あるいは小さい）という条件を満たすもの。
また、コンピュータプログラムが利用するメモリ領域の種類の一つで、実行時に任意の
タイミングで確保や解放が可能なものをヒープ領域というが、これをヒープと略す場合がある。

ヒープ領域 (ヒープメモリ)
コンピュータプログラムが実行時に使用するメモリ領域の一つで、任意に確保や解放を
繰り返すことができるものをヒープ領域、あるいはヒープメモリ（heap memory）という。
これを指して単にヒープと略すことも多く、データ構造のヒープと混同しないよう文脈に
注意する必要がある。

ヒープにデータを置く時、あるサイズのスペースを求めます。 OSはヒープ上に十分な
大きさの空の領域を見つけ、使用中にし、ポインタを返してきます。
ポインタとは、その場所へのアドレスです。 
この過程は、ヒープに領域を確保すると呼ばれ、時としてそのフレーズを単にallocateする
などと省略したりします。


[所有権規則]
    ・Rustの各値は、所有者と呼ばれる変数と対応している。
    ・いかなる時も所有者は一つである。
    ・所有者がスコープから外れたら、値は破棄される。


[リテラル literal]
リテラルとは、コンピュータプログラムのソースコードなどの中に、特定のデータ型の値を
直に記載したもの。また、そのように値をコードに書き入れるために定められている書式。

表記の仕方によってデータ型を識別できるよう、例えば文字列を表記する際は必ず
前後を「"」で括る、といった書式が言語仕様によって定められている。
各データ型のリテラルを、型名を先頭につけて「文字列リテラル」「整数リテラル」
「日付リテラル」などと呼ぶ。


[シャローコピー ディープコピー shallow copy deep copy]
シャローコピーというのは、コピー元のオブジェクトとコピー先のオブジェクトがメモリ上の
同じデータ(インスタンス変数)を参照しています。
ですので、コピー元のオブジェクトに対してインスタンス変数に変更を加えると、コピー先の
オブジェクトが参照しているデータが同じ物なので、コピー先のオブジェクトから見た
インスタンス変数も変更されることになります。
シャローコピーは、参照のコピーのみを行うということですね。

ディープコピーは、オブジェクトのみのコピーではなく、オブジェクトとメモリ上のデータ
(インスタンス変数)の両方をコピーする。
二つのオブジェクトが参照しているデータは別々のものなので、一方のオブジェクトの
ンスタンス変数に変更を加えても、もう一方のオブジェクトには影響を与えません。


[Copyの型 コピーの型]

        ◎あらゆる整数型。u32など。
        ◎論理値型、bool、trueとfalseという値がある。
        ◎あらゆる浮動小数点型、f64など。
        ◎文字型、char。
        ◎タプル。ただ、Copyの型だけを含む場合。例えば、(i32, i32)はCopyだが、 
        (i32, String)は違う。


[isize型 usize型]
isizeとusize型は、整数型であり、プログラムが動作しているコンピュータの種類に
依存します。
64ビットアーキテクチャなら、64ビットですし、32ビットアーキテクチャなら、
32ビットになります。


[rustのアップデート update]
windowsでもlinuxでも
rustup update
でOK


[stringを空にする]
let mut a = String::from("hello world");
とすると
a.clear();
で
aは""となる


[文字列スライスを表す型]
文字列スライスを意味する型は
&str
である

let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];


[構造体 struct]
struct はより複雑なデータ型を作る方法の1つです。例えば、もし私たちが2次元空間の
座標に関する計算を行っているとして、 x と y 、両方の値が必要になるでしょう。

let origin_x = 0;
let origin_y = 0;

struct でこれら2つを1つのデータ型にまとめることができます。

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

fn main() {
    let origin = Point { x: 0, y: 0 }; // origin: Point

    println!("The origin is at ({}, {})", origin.x, origin.y);
}

ここで多くの情報が出てきましたから、順番に見ていきましょう。まず、 struct キーワードを
使って構造体とその名前を宣言しています。
慣習により、構造体は初めが大文字のキャメルケースで記述しています。 
PointInSpace であり、 Point_In_Space ではありません。

いつものように、 let で struct のインスタンスを作ることができますが、ここでは
key: value スタイルの構文でそれぞれのフィールドに値をセットしています。
順序は元の宣言と同じである必要はありません。

最後に、作成された構造体のフィールドは名前を持つため、 origin.x というようにドット表記で
アクセスできます。

Rustの他の束縛のように、 struct が持つ値はイミュータブルがデフォルトです。 mut を使うと
値をミュータブルにできます。

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

fn main() {
    let mut point = Point { x: 0, y: 0 };

    point.x = 5;

    println!("The point is at ({}, {})", point.x, point.y);
}

これは The point is at (5, 0) と出力されます。

Rustは言語レベルでフィールドのミュータビリティに対応していないため、以下の様に書くことは
できません。

struct Point {
    mut x: i32,
    y: i32,
}

ミュータビリティは束縛に付与できる属性であり、構造体自体に付与できる属性ではありません。
もしあなたがフィールドレベルのミュータビリティを使うのであれば、初めこそ奇妙に見える
ものの、非常に簡単に実現できる方法があります。以下の方法で少しの間だけミュータブルな
構造体を作ることができます。

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

fn main() {
    let mut point = Point { x: 0, y: 0 };

    point.x = 5;

    let point = point; // この新しい束縛でここから変更できなくなります

    point.y = 6; // これはエラーになります
}


[フィールド field]
異なる種類のデータなどが集まってできた何らかの構造体における個々の項目や要素を
意味する。


[guessing_game]
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("数字を当ててください!");

    let secret_number = rand::thread_rng().gen_range(1, 101); 
    
    loop{
        println!("１から１００のまでの間の秘密の数字を入力して当ててください");

        let mut guess = String::new();

        io::stdin().read_line(&mut guess)
            .expect("入力を読み込めませんでした");

        let guess: u32 = match guess.trim().parse(){  
            Ok(num) => num,
            Err(_) => continue,
        };
    
        println!("あなたの入力したのは: {}", guess);
    
        match guess.cmp(&secret_number)  {
            Ordering::Less    => println!("小さすぎます!"),
            Ordering::Greater => println!("大きすぎます!"),
            Ordering::Equal   => {
                println!("大当たり!");
                break;
            }
        }
    }
}


[ダングリングポインタ]
ダングリングポインタとは、 他人に渡されてしまった可能性のあるメモリを指すポインタの
ことであり、その箇所へのポインタを保持している間に、 メモリを解放してしまうことで
発生します。
対照的にRustでは、コンパイラが、 参照がダングリング参照に絶対ならないよう保証して
くれます: つまり、何らかのデータへの参照があったら、 コンパイラは参照がスコープを
抜けるまで、データがスコープを抜けることがないよう確認してくれるわけです。


[オブジェクトをバイト配列に変換する]
let s = String::from("ハロー");
let bytes = s.as_bytes();


[イテレータ iter]
iterは、コレクション内の各要素を返すメソッドである


[シグニチャ　シグネチャ　signature]
《コ》シグネチャー◆対象を同定するための目印となる情報。
メソッドのシグネチャー（method signature）、ウイルスのシグネチャー（virus signature）
など。

《コ》署名、フッター、シグネチャー◆ユーザーの設定により、メールの文章やフォーラムでの
投稿の末尾に自動付加される短いテキストや画像。
典型的には、その人の連絡先・ウェブサイトのアドレス・お気に入りの名言などが書かれている。
◆口語では、しばしばsigと略される。


[Rustacean]
A user of the Rust programming language.


[タプル構造体]
タプル構造体は、構造体名が提供する追加の意味は含むものの、 フィールドに紐付けられた
名前はありません; むしろ、フィールドの型だけが存在します。
タプル構造体は、タプル全体に名前をつけ、 そのタプルを他のタプルとは異なる型にしたい場合に
有用ですが、普通の構造体のように各フィールド名を与えるのは、 冗長、または余計になるでしょう。

タプル構造体を定義するには、structキーワードの後に構造体名、さらにタプルに含まれる型を
続けます。 
例えば、こちらは、ColorとPointという2種類のタプル構造体の定義と使用法です:

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);


[メソッド]
メソッドは関数に似ています: fnキーワードと名前で宣言されるし、引数と返り値があるし、 
どこか別の場所で呼び出された時に実行されるコードを含みます。ところが、 メソッドは構造体の
文脈(あるいはenumかトレイトオブジェクトの。)で定義されるという点で、 関数とは異なり、
最初の引数は必ずselfになり、これはメソッドが呼び出されている構造体インスタンスを表します。

メソッドを定義する

Rectangleインスタンスを引数に取るarea関数を変え、代わりにRectangle構造体上にarea
メソッドを作りましょう。 下記に示した通りですね。

ファイル名: src/main.rs

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

もう一つのサンプル(自作例)
fn main() {
    let person1 = X {
        height: 1.64,  // 身長(M)
        weight: 55.0,  // 体重(KG)
    };
    
    let person2 = X {
        height:1.7,
        weight: 72.0,
    };
    
    println!("person1.weight = {}",person1.weight);
    println!("person1.height = {}",person1.height);
    println!("bmi1 = {}", person1.bmi());
    println!("");
    
    println!("person2.weight = {}",person2.weight);
    println!("pweson2.height = {}",person2.height);
    println!("bmi2 = {}", person2.bmi());

}

struct X {
    height: f32,
    weight: f32,
}

impl X {
    fn bmi (&self) -> f32 {
        self.weight / self.height / self.height
    }
}


[キーボードから入力する コンソールから入力する]
use std::io;
fn main() {
        let mut guess = String::new();
        io::stdin().read_line(&mut guess)
            .expect("入力を読み込めませんでした");
}


[コンストラクタ constructor]
コンストラクタ（構築子[1]、英: constructor）は、オブジェクト指向の
プログラミング言語で新たなオブジェクトを生成する際に呼び出されて内容の
初期化などを行なう関数あるいはメソッドのことである。対義語はデストラクタ。

オブジェクトの生成は、

    メモリ割当（英: allocation）
    初期化（英: initialization）

の二段階を経て行われるが、コンストラクタを持つプログラミング言語では
メモリ割当は言語機能に組み込まれ、初期化用のコードのみを記述するのが
普通である。 


[列挙型 emun]
列挙型は、enumとも称されます。enumは、取りうる値を列挙することで、 
型を定義させてくれます。
enumは多くの言語に存在する機能ですが、その能力は言語ごとに異なります。
Rustのenumは、F#、OCaml、Haskellなどの、 関数型言語に存在する代数的
データ型に最も酷似しています。

#![allow(unused_variables)]

enum IpAddrKind {
    V4,
    V6,
}

fn main() {
    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;
}


[改行無しで画面に出力する]
print! を使用する

例
fn main() {
    let txt1 = String::from("I am a boy");
    let txt2 = String::from("You are a girl");
    print!("{} {}",txt1,txt2);
}

出力結果
I am a boy You are a girl


[ファイルの内容全体を文字列として一気に読み込み]
Rust v1.26.0以降に追加されたstd::fs::read_to_stringを使用すると
簡単です。
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let content = fs::read_to_string("path/to/file")?;
    println!("{}", content);
    Ok(())
}

他にはRead traitのread_to_stringメソッドを使ったやり方もあります。
use std::io::{self, Read};

fn get_content<R: Read>(r: &mut R) -> io::Result<String> {
    let mut buf = String::new();
    let _ = r.read_to_string(&mut buf)?;
    Ok(buf)
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let content = get_content(&mut io::stdin())?;
    println!("{}", content);
    Ok(())
}


[1行ずつ文字列を読み込みたい]
use std::io::{BufReader,BufRead}; 
use std::fs::File; 

fn main() { 
    let file = File::open("file.txt").unwrap(); 
    for line in BufReader::new(file).lines() { 
     println!("{}", line.unwrap()); 
    } 
} 


[ファイルの内容全体をバイト列として一気に読み込み]
Read traitのread_to_endメソッドを使います。

use std::fs::File;
use std::io::Read;

fn main() -> Result<(), Box<std::error::Error>> {
    let mut file = File::open("path/to/file")?;
    let mut buf = Vec::new();
    let _ = file.read_to_end(&mut buf)?;
    println!("{:?}", buf);
    Ok(())
}


[バイト列をバッファに読み込みながら処理したい]
use std::fs::File;
use std::io::{Read, BufReader};

fn main() -> Result<(), Box<std::error::Error>> {
    let mut reader = BufReader::new(File::open("path/to/file")?);
    let mut buf = [0; 4];

    loop {
        match reader.read(&mut buf)? {
            0 => break,
            n => {
                let buf = &buf[..n];
                println!("{:?}", buf);
            }
        }
    }

    Ok(())
}

何らかの理由でBufReaderのバッファリングが邪魔な場合はRead traitの
readメソッドを自分で呼び出して読み込んでいきます。
use std::fs::File;
use std::io::Read;

fn main() -> Result<(), Box<std::error::Error>> {
    let mut file = File::open("path/to/file")?;
    let mut buf = [0; 4];

    loop {
        match file.read(&mut buf)? {
            0 => break,
            n => {
                let buf = &buf[..n];
                println!("{:?}", buf);
            }
        }
    }

    Ok(())
}


[面倒な事は一切しないで1バイトずつ処理したい]
BufReaderを通してRead traitのbytesメソッドを呼びます。

use std::fs::File;
use std::io::{Read, BufReader};

fn main() -> Result<(), Box<std::error::Error>> {
    for result in BufReader::new(File::open("path/to/file")?).bytes() {
        let byte = result?;
        println!("{:x}", byte);
    }

    Ok(())
}


[文字列/バイト列を一度に書き出す]
自分でバッファリングしてWrite traitのwrite_allメソッドを使って書き出します。
書き込み可能なファイルハンドルはFile型のcreateメソッドで作成します。
use std::fs::File;
use std::io::{self, Read, Write, BufReader};

fn main() -> Result<(), Box<std::error::Error>> {
    let mut file = File::create("path/to/file")?;
    let buf = BufReader::new(io::stdin()).bytes().collect::<io::Result<Vec<u8>>>()?;
    file.write_all(&buf)?;
    file.flush()?;
    Ok(())
}

バイト列ではなく文字列の場合はwrite!またはwriteln!マクロを使う事で
println!と同じ様に書きだす事ができます。
use std::fs::File;
use std::io::{self, BufRead, Write, BufReader};

fn main() -> Result<(), Box<std::error::Error>> {
    let mut file = File::create("path/to/file")?;
    let buf = BufReader::new(io::stdin()).lines().collect::<io::Result<Vec<String>>>()?.join("\n");
    write!(file, "{}", buf)?;
    file.flush()?;
    Ok(())
}


[文字列/バイト列を少しずつ複数回に分けて書き出す]
BufWriterを使う事以外は一度に書き出す場合と基本は同じです。
use std::fs::File;
use std::io::{self, Read, Write, BufReader, BufWriter};

fn main() -> Result<(), Box<std::error::Error>> {
    let mut writer = BufWriter::new(File::create("path/to/file")?);
    for result in BufReader::new(io::stdin()).bytes() {
        let byte = result?;
        writer.write_all(&[byte])?;
    }
    file.flush()?;
    Ok(())
}


[ループを抜ける break]
ループから抜け出すには break を利用し、loop は式であるため、後続する値を返します。
fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("The result is {}", result);
}


[イテレータ iterator "Returns an iterator over the slice."]
配列の場合、 iterator （Returns an iterator over the slice.）により、
配列要素を一つずつ呼び出し、 x に入れて回していきます。 
iterator は Some or None であるため、 for 自体は None が与えられるまで
回し続けるようです。

fn main() {
    let a = [1, 2, 3, 4, 5];

    for x in a.iter() {
        println!("x -> {}", x);
    }
}
結果
x -> 1
x -> 2
x -> 3
x -> 4
x -> 5


[パーサ parser パーザ]
パーサとは、プログラムのソースコードやXML文書など、一定の文法に従って記述された
複雑な構造のテキスト文書を解析し、プログラムで扱えるようなデータ構造の集合体に
変換するプログラムのこと。そのような処理のことを「構文解析」「パース」（parse）という。

パーサはそれ単体で利用されることはあまりなく、何らかの処理をするための前段階として
使われることが多いため、汎用のサブルーチンやモジュール、ライブラリなどとして
提供されることが多い。


[デプロイ deploy]
デプロイ（英: deploy）とは、「配置する」「配備する」「展開する」といった意味の
英語の動詞です。
日本語の中では、ソフトウェア開発の工程のうち、開発した機能やサービスを利用できる
状態にする作業を指す語として用いられています。

デプロイに該当する作業としては、たとえば、ウェブアプリケーションの開発において、
作製したプログラムをサーバーにアップロードし、当該のサーバー環境で利用可能にする、
という手続きが挙げられます。
ただし、必ずしも公開（リリース）作業を指すとは限らず、開発環境からテスト用の環境へ
アップロードしてテストに使える状態にすることもデプロイといいます。
ソフトウェアをインストールする作業もデプロイに該当します。 


[projectsの中身を初期化する]
cargo clean


[円の面積の計算 πの値 ２乗計算]
fn main() {
    println!("半径 {:.3}, 円周率 {:.3}, 面積 {:.3}",
        3.2,
        std::f64::consts::PI,
        3.2f64.powi(2) * std::f64::consts::PI,
    );
}


[逆ポーランド記法]
逆ポーランド記法（ぎゃくポーランドきほう、英語: Reverse Polish Notation, RPN）は、
数式やプログラムの記法の一種。
演算子を被演算子の後にすることから、後置記法 (Postfix Notation) とも言う。
例えば、「3 と 4 を加算する」という演算を、一般的に数式の表記に用いられる中置記法で
記述すると、以下のようになる。

3 + 4

一方、逆ポーランド記法では、加算を表す演算子 + を、被演算子である 3 と 4 の後（右）に
置いて、以下のよう記述する。

3 4 +

逆ポーランド記法による表現は日本語などSOV型の言語の語順とある程度似ており、上式程度で
あれば「3 と 4 を加算する」とそのままの順序で読み下せる。
逆ポーランド記法を使うForthの影響を受けているプログラミング言語Mindでは、
「3と 4とを 足す」と書く。

もう少し複雑な例として、中置記法による以下の式は、

(3 + 4) * (1 - 2)

逆ポーランド記法で記述すると以下の通りとなる。

3 4 + 1 2 - *


[Visual Studio Code VS Code のインストール]
1. パッケージのダウンロード
    https://code.visualstudio.com/download
    から必要なパッケージをダウンロードする。
    
2. パッケージの実行

3. 日本語化
    画面左のツールバーにある「extension」をクリックする
    「Serch Extensions in Marketplace」欄に「Japanese」を入力する
    すると「Japanese Language Pack」が現れるのでJapaneseに関係する
    ものをインストールしてから、VS Code を再起動する。
    つまり
        Japanese Language Pack for Visual Studio Code
        Japanese Word Handler
        Japanese Support for Language Tool
    である。
    
4. Rust RLS 拡張機能のインストール
    画面左のツールバーにある「extension」をクリックする
    「rust-lang」を検索して
        Rust(rls)
    をインストールする


[キーボードから文字を入力する]
use std::io; 
use std::io::Write; // <--- bring flush() into scope 

fn main() { 
    println!("I'm picking a number between 1 and 100..."); 

    print!("Enter a number: "); 
    io::stdout().flush().unwrap(); 
    let mut val = String::new(); 

    io::stdin().read_line(&mut val) 
     .expect("Error getting guess"); 

    println!("You entered {}", val); 
} 


[Rustの基本的な文法]

変数
    変数の宣言は以下のようにする。
    let num = 10;
    
    型を示すこともできる。
    let num: i32 = 100;
    
    Rustでは変数はデフォルトでイミュータブルになっていて、書き換えることはできない。
    let x = 5;
    x = 10; // コンパイルエラー
    
    ミュータブルにしたいときはmutを付ける
    let mut x = 5;
    x = 10;

    また、未初期化の変数を宣言することはできるが、使用しようとするとコンパイルエラーになる。
    let x: i32;
    println!("{}", x); // コンパイルエラー

プリミティブ型
    bool
    おなじみの真偽値。true or false
    let changed: bool = true;

    char
    文字を表す。ユニコードに対応している。
    let ch: char = 'a';
    let poop: char = '💩';

    i8
    i16
    i32
    i64

    符号あり整数型。数値はビット数を表す。
    let x: i32 = 1234;
    let y: i16 = -100;

    u8
    u16
    u32
    u64

    符号なし整数型。こちらも数値はビット数を表す。
    let x: u32 = 1234;
    let y: u16 = -100; // コンパイルエラー

    isize
    usize

    実行環境のポインタサイズで変わる型。32bitではi32 or u32、64bitではi64
     or u64になるということかな。

    f32
    f64

    浮動小数点数型。数値は単精度か倍精度かを表す。
    let pi: f32 = 3.1415926535;

    配列
    おなじみの配列。要素の型はすべて同じにしないといけない。
    let a: [i32; 3] = [1, 2, 3];
    let x = a[0] + a[1]; // x = 3
    配列の初期化
        let mut x:[&str;32] = Default::default();
            この場合、32が最大値
        let mut x: [&str; 50] = [" "; 50];
        let array: [i32; 50] = [1; 50];
            これら場合32を超えても可
    配列の中の数字（例えば x[j] の j のこと）は usize でなければならない。
        usize を u32 に変換するには
            a.try_into().unwrap()
            とする。
            use std::convert::TryInto;
            を忘れずに

    タプル
    固定サイズのリスト。要素の型は異なっても良い。
    let t: (i32, f32) = (3 0.141592);
    let x = t.0 + 3;


[cargo clean 使い方]
「cargo clean」コマンドを実行すると、target以下を削除してくれます。


[よく使われる文字列操作からピックアップ]
文字数
    文字列のバイト数は、
    fn main(){
        let a = String::from("あいうえお");
        let b = a.len();
        println!("長さ = {}",b);
    }
    出力結果は、
    長さ = 15

文字列の結合(join)
    assert_eq!("Hello World", ["Hello", "World"].connect(" "));
    こちらは単に結合するだけ。一般のVecに対するflatternメソッドとして使える
    let d: String = ["Hello", "World"].concat();
    assert_eq!("HelloWorld", d);

文字列の分割
    "a.b.c".split('.');  // => iterator of ["a", "b", "c"]
    "a..b..c".split_str(".");  // => iterator of ["a", "b", "c"]

置換
    assert_eq!("adeade", "abcabc".replace("bc", "de"));  // replaceは
    in-place演算ではない。新しい文字列を作って返す

部分文字列が含まれているか調べる
    fn main() {
        et a = String::from("今日の天気は晴れでした");
        let b = String::from("雨");
        if a.contains(&b) {
            println!("yes");
        }
        else {
            println!("no");
        }
    }

部分文字列を得る
    assert_eq!("b", "abc".slice_chars(1, 2));

部分文字列の出現回数をカウントする
    対応するメソッドがないのでmatch_indicesを介する
    assert_eq!(2, "xabxxabxxbc".match_indices("ab").count());

trim/strip
    assert_eq!("abc1def", "11abc1def11".trim_matches('1'));
    assert_eq!("a", " 　a".trim_left());


[アサーション assertion assert!()]
アサーションとはプログラムの形式検証における成立条件である

assert!()の使い方
第一引数が条件で、第二数以降はアサーション時のメッセージ表示用、println! と同じように
出力フォーマットを指定できる。
fn main(){
    let a = 2;
    let b = 3;
    assert!(a == b,"NO");
}
出力結果
thread 'main' panicked at 'NO', src\main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\trial.exe` (exit code: 101)

assert_eq! マクロ
同値条件専用の assert!。第1引数と第２引数を比較する。
fn main() {
  let x = 1;
  let y = 2;

  debug_assert!(x <= y, "{} > {}", x, y);
  debug_assert_eq!(x, y);

  assert!(x <= y, "{} != {}", x, y);
  assert_eq!(x, y);
}


[パース parse]
パースとは、文法に従って分析する、品詞を記述する、構文解析する、などの意味を持つ英単語。

コンピュータプログラムの機能・処理の一つで、一定の書式や文法に従って記述されたデータを解析し、
プログラムで扱えるようなデータ構造の集合体に変換することをパースという。
そのためのソフトウェアやプログラム部品などのことを「パーサ」（parser）あるいは「パーザ」という。

例えば、コンパイラなどがプログラムのソースコードを機械語の表現に変換するために語彙や構文などの
構造を解析することや、WebブラウザがHTMLファイルを表示するためにタグの構造や属性などを解析して
表示可能なデータ構造に変換することなどを指す。


[コマンドライン引数]
引数の値を読み取る
    use std::env;

    fn main() {
        let args: Vec<String> = env::args().collect();
        println!("{:?}", args);
    }

引数の値を変数に保存する
    use std::env;

    fn main() {
        let args: Vec<String> = env::args().collect();

        let fst = &args[1];
        let secnd = &args[2];

        // {}を探しています
        println!("First 引数 =  {}", fst);
        // {}というファイルの中
        println!("second 引数 = {}", second);
    }

オプショナルな引数、例えば -h や -help でヘルプを処理する、
あるいは必須の引数が与えられなかったときにエラーを返す
    Cargo.toml に下記追加
        clap = "2.33.0"
    
    // clapで定義されている clap::app と clap::Arg の
    // ２つの型をスコープに入れる
    use clap::{App,Arg};

    fn main() {
    // clap::App でコマンド名やバージョンなどを設定
    let arg_matches = App::new("trip-analyzer")
        .version("1.0")
        .about("Analyzer yellow cab trip records")
        // INFILE という名前のコマンドライン引数を登録
        .arg(Arg::with_name("INFILE")
        .help("Sets the input CSV file")
        .index(1)  // 最初の引数
        )
        // get_matches() メソッドを呼ぶとユーザーが与えた
        // コマンドライン引数がパースされる
        .get_matches();
   
        // INFILE の文字列を表示。"{:?} はデバッグ用文字列を表示
        println!("INFILE: {:?}", arg_matches.value_of("INFILE"));
    }

    get-matches()メソッドを呼ぶと、ユーザーが与えたコマンドライン引数が
    パースされ、clap::ArgMatches型の値が返される。
    そして ArgMatches の value_of() メソッドはコマンドライン引数を
    文字列として返す。


[option型 オプション型]
Rustが標準ライブラリで提供している型 Option<T> はジェネリックです。
enum Option<T> {
    None,  // None バリアント
    Some(T), // Some バリアント。T型の値を持つ
}
<T> の部分は、前に少し見たことがあると思いますが、これがジェネリックなデータ型で
あることを示しています。 enum の宣言内であれば、どこでも T を使うことができ、
宣言内に登場する同じ型をジェネリック内で T 型に置き換えています。
型注釈を用いたOption<T>の使用例が以下になります。

let x: Option<i32> = Some(5);

この型宣言では Option<i32> と書かれています。 Option<T> の違いに注目して下さい。
そう、上記の Option では T の値は i32 です。この束縛の右辺の Some(T) では、
T は 5 となります。それが i32 なので、両辺の型が一致するため、Rustは満足します。
型が不一致であれば、以下のようなエラーが発生します。

let x: Option<f64> = Some(5);
// error: mismatched types: expected `core::option::Option<f64>`,
// found `core::option::Option<_>` (expected f64 but found integral variable)


[Result型]
Result<T,E>型
Result<T,E>は失敗するかもしれない処理の結果を表現する列挙型です。
Resultはrustコンパイラから特別扱いされており、無視するとwarinigが出ます。
Resultは例外がないrustにおける標準のエラーハンドリング方法です。
エラーが発生する可能性がある場合は結果にResultを用いるようにしましょう。

enum Result<T, E> {
   Ok(T),
   Err(E),
}

他言語で例外を利用したり、エラーコードを返したいような場合に利用します。
Result型の戻り値を無視するとwarningが出るのでエラーハンドリングして
いないことに気づけますし、パターンマッチで取り出せて例外より取り回し
やすいのが良いです。

fn get_value_bad(v: bool, result: &mut usize) -> usize {
    if v {
        *result = 100;
        0 
    } else {
        1
    }
}

fn get_value_good(v: bool) -> Result<usize,&'static str> {
    if v {
        Ok(100)
    } else {
        Err("error message")
    }
}

fn main() {
    // エラーコードを返す書き方
    // 利用者が戻り値を無視できるのでよく無い
    let mut result = 0;
    if get_value_bad(true, &mut result) == 0 {
        println!("success: {}", result);
    } else {
        println!("failure");
    }

    // rustぽい書き方
    match get_value_good(true) {
        Ok(result) => println!("success: {}", result),
        Err(msg) => println!("failure: {}", msg),
    }
}


[stdクレートのドキュメントを読む方法]
$ rustup doc --std


[unwrapとは]
unwrap() は、 Option<T> 型や Result<T, E> 型の値（つまり、何かしらの値を 
ラップ している値）から中身の値を取り出す関数です。たとえば Option<T> 型の
値に対して unwrap() を呼ぶと、それが内包する T 型の値を返します。

unwrap() は失敗するかもしれないことに注意が必要です。 Option<T> 型や 
Result<T, E> 型などの値は、 T 型の値が入っていることもあれば入っていない
こともあります。入っていない場合に unwrap() を呼ぶとプログラムは panic します。

let opt: Option<i32> = Some(42);
println!("{}", opt.unwrap()); // 42 を表示
let opt: Option<i32> = None;
println!("{}", opt.unwrap()); // ここで panic

unwrap() は記述を簡潔にするためサンプルコードで使用されることがありますが、
普段は使用を避けてパターンマッチや unwrap_or() などの安全な関数で値を
取り出したほうがいいでしょう。

let opt: Option<i32> = None;
match opt {
    Some(_) => println!("some!"),
    None => println!("none!"),
}
// none! を表示

println!("{}", opt.unwrap_or(0)); // 0 を表示

動作は unwrap() と同じですが panic したときのカスタムメッセージを指定できる 
expect() もあります。値が入っていることが確実に分かっていて、そうでなければ
バグとしてクラッシュしていいという場合には expect() を使ってもよいでしょう。

RefCell<T> なども何かしらの値をラップしている値といえますが、この場合は 
T 型の値が入っていることが保証されています。必ず中身が入っている型から
内包された値を取り出す関数は、panic しないことを明確にするため unwrap() 
ではなく into_inner() と命名されています。


[プログラムを中断する exit]
use std::process::exit;

fn main(){
    println!("これはNo.1");
    exit(0);
    println!("これはNo.2");
}


[ディレクトリリストを表示、dir ls の機能]
use std::fs;
fn main() {
    let paths = fs::read_dir("./").unwrap();

    for path in paths {
        print!("{}", path.unwrap().path().display());
        println!();
    }
}

もう一つの方法
use std::fs;

fn main() {
    let target = "./";
    let mut files: Vec<String> = Vec::new();
    for path in fs::read_dir(target).unwrap() {
        files.push(path.unwrap().path().display().to_string().replacen(target, "", 1))
    }

    files.sort();
    let strings = files.iter()
        .fold(String::new(), |joined, s| {
            if joined == String::new() { s.to_string() } else { joined + "\n" + s }
        });

    println!("{}", strings)
}


[文字を表す]
char型は値としてUnicodeの1文字（正確には1つのUnicodeスカラ値）を持つ。
char型は1文字を表すのに必ず4バイト使用する。
charリテラルはシングルクォートで作れる。文字列を作るダブルクォーテーションとは違うので注意。

let c1 = 'A';               // 文字型
let c2 = 'a';
assert!(c1 < c2);           // 文字コード順で大小比較
assert!(c1.is_uppercase()); // 大文字か検査
 
let c3 = '0';
assert!(c3.is_digit(10));   // 10進数の数字か検査
 
let _c4 = '\t';             // タブ文字
let _c5 = '\n';             // 改行（LF）文字
let _c6 = '\'';             // シングルクォート（'）
let _c7 = '\\';             // バックスラッシュ（\）
let _c8 = '\x7F';           // 制御文字delを8ビットコードで表現（16進数で2桁）
 
let _c9 = '漢';             // ソースコードに直接漢字もかける
let _c10 = '\u{5b57}';      // '字'をユニコードのエスケープコードで表現
							   // (16進数で最大6文字)
let _c11 = '\u{1f600}'; // 絵文字
 
// char型は1文字を表すのに、たとえ英数字であっても4バイト
assert_eq!(std::mem::size_of::<char>(), 4); // サイズは4バイト


[後置演算子]
?後置演算子
Result型やOption型の値を扱うときに便利な演算子です。
Result型の値に ? 演算子を適用すると次に様になります。
Ok(T)なら、包んでいる値を取り出します。
let mut reader = csv::Reader::from_path(infile)?;
のコードではその値が変数 reader にセットされます。
Err(E)なら、すぐに関数からリターンし、呼び出し元に Err(E) の値を返します。
もし、 Err(E) と戻り値型 Result<T,E> の E が一致しないのなら値を変換します。


[名前を_で始めて未使用の変数を無視する]
変数を作っているのにどこでも使用していなければ、バグかもしれないのでコンパイラは通常、
警告を発します。 
しかし時として、まだ使用しない変数を作るのが有用なこともあります。
プロトタイプを開発していたり、 プロジェクトを始めた直後だったりなどです。
このような場面では、変数名をアンダースコアで始めることで、 コンパイラに未使用変数について
警告しないよう指示することができます。
リスト18-20で2つの未使用変数を生成していますが、 このコードを実行すると、そのうちの
1つにしか警告が出ないはずです。

ファイル名: src/main.rs

fn main() {
    let _x = 5;
    let y = 10;
}

リスト18-20: アンダースコアで変数名を始めて未使用変数警告が出るのを回避する

ここで、変数yを使用していないことに対して警告が出ていますが、アンダースコアが接頭辞に
なっている変数には、 使用していないという警告が出ていません。

_だけを使うのとアンダースコアで始まる名前を使うことには微妙な違いがあることに注意して
ください。 
_x記法はそれでも、値を変数に束縛する一方で、_は全く束縛しません。
この差異が問題になる場合を示すために、 リスト18-21はエラーを提示するでしょう。

// こんにちは！
let s = Some(String::from("Hello!"));

if let Some(_s) = s {
    // 文字列が見つかりました
    println!("found a string");
}

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

リスト18-21: それでも、アンダースコアで始まる未使用の変数は値を束縛し、値の所有権を奪う
可能性がある

それでもs値は_sにムーブされ、再度sを使用できなくするので、エラーを受け取るでしょう。
ですが、 アンダースコアを単独で使用すれば、値を束縛することは全くありません。 
sが_にムーブされないので、リスト18-22はエラーなくコンパイルできます。

let s = Some(String::from("Hello!"));

if let Some(_) = s {
    println!("found a string");
}

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

リスト18-22: アンダースコアを使用すると、値を束縛しない

このコードは、sを何にも束縛しないので、ただ単に上手く動きます。
つまり、ムーブされないのです。


[コード内で不使用の変数へのアラームを非表示にする unused_variables]
    fn main() の外側に書きを記述追加する。
    #![allow(unused_variables)]


[文字列エスケープ escape]
ASCIIエスケープ
	名前
    \x41 	7ビット文字コード（正確に2桁、最大0x7F）
    \n 	改行
    \r 	キャリッジリターン
    \t 	タブ
    \\ 	バックスラッシュ
    \0 	ヌル
    
バイトエスケープ
	名前
    \x7F 	8ビット文字コード（正確に2桁）
    \n 	改行
    \r 	キャリッジリターン
    \t 	タブ
    \\ 	バックスラッシュ
    \0 	ヌル

Unicodeエスケープ
	名前
    \u{7FFF} 	24ビットUnicode文字コード（最大6桁）
    
引用エスケープ
	名前
    \' 	一重引用符
    \" 	二重引用符


[Rustの整数リテラル]
数値リテラル 	    例
-------------------------------
10進数 	            98_222
16進数 	            0xff
8進数 	            0o77
2進数 	            0b1111_0000
バイト (u8だけ) 	b'A'


[second_word]
#![allow(unused_variables)]

fn main() {

    let s = String::from("hello world This is a pen");

    let c = first_word(&s);
    println!("Fitst word = {}",c);
    
    let d = second_word(&s);
    println!("Second word = {}",d);

}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    
    for(i,&item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

fn second_word(s: &String) -> &str{
    let bytes = s.as_bytes();
    
    let mut h: usize = 0;
    let mut j: usize =0;
    for(i,&item) in bytes.iter().enumerate() {
        if item == b' ' {
            if h != 1 {
                h = 1;
                j = i + 1;
            }
            else {
                return &s[j..i];
            }
        }
    }

    if h == 1 {
        return &s[j..];
    }
    &s[..]
}


[関連関数]
implブロックの別の有益な機能は、implブロック内にselfを引数に取らない関数を
定義できることです。 これは、構造体に関連付けられているので、関連関数と
呼ばれます。それでも、関連関数は関数であり、メソッドではありません。 
というのも、対象となる構造体のインスタンスが存在しないからです。
もうString::fromという関連関数を使用したことがありますね。

関連関数は、構造体の新規インスタンスを返すコンストラクタによく使用されます。
例えば、一次元の引数を取り、 長さと幅両方に使用する関連関数を提供することができ、
その結果、同じ値を2回指定する必要なく、 正方形のRectangleを生成しやすくすることが
できます。

ファイル名: src/main.rs

impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle { width: size, height: size }
    }
}

この関連関数を呼び出すために、構造体名と一緒に::記法を使用します; 
一例はlet sq = Rectangle::square(3);です。 
この関数は、構造体によって名前空間分けされています: ::という記法は、関連関数と
モジュールによって作り出される名前空間両方に使用されます。


[名前空間 Namespace]
名前空間（なまえくうかん）はNamespaceの訳語で、名前の集合を分割することで衝突の
可能性を低減しつつ参照を容易にする概念である。

この集合は、全事象の元の全ての組み合わせ可能なものからなる集合全体および物理的な
名称を指すことが可能である。
つまり英字・数字・記号などを組みあわせて作られる名前全てを含む集合である。
名前に結び付けられる実体（型や変数）は、名前がそれぞれどの集合（空間）に属するか
指定されることで一意に定まる。名前空間が異なれば同じ名前でも別の実体に対応付けられる。 


[CSVを読み込んで表示する]
Cargo.tomlファイルに下記追加する

[dependencies]
csv = "1.1"

以下、ソースコードの本文
extern crate rust;

use self::rust::*;
use std::io;
use std::process;

fn read() -> Result<(), Box<dyn Error>> {
    let mut rdr = csv::Reader::from_reader(io::stdin());
    for result in rdr.records() {
        let record = result?;
        let title = &record[0];
        let body = &record[1];
        println!("title: {}", &title);
        println!("body: {}", &body);
    }
    Ok(())
}

fn main() {
    if let Err(err) = read() {
        println!("error running read: {}", err);
        process::exit(1);
    }
}


[cargo run で引数を指定して実行する]
cargo run 引数


[パスが存在するかどうかを確認する]
use std::fs; 

pub fn path_exists(path: &str) -> bool { 
    fs::metadata(path).is_ok() 
} 

fn main() { 
    println!("{}", path_exists("/etc/hosts")); 
} 


[行単位でファイルを読み込む]
use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let filename = "src/main.rs";
    // Open the file in read-only mode (ignoring errors).
    let file = File::open(filename).unwrap();
    let reader = BufReader::new(file);

    // Read the file line by line using the lines() iterator from std::io::BufRead.
    for (index, line) in reader.lines().enumerate() {
        let line = line.unwrap(); // Ignore errors.
        // Show the line and its number.
        println!("{}. {}", index + 1, line);
    }
}


[データをファイルに追加する]
use std::fs::OpenOptions;
use std::io::Write;

fn main() {
   let mut file = OpenOptions::new().append(true).open("data.txt").expect(
      "cannot open file");
   file.write_all("Hello World".as_bytes()).expect("write failed");
   file.write_all("\nTutorialsPoint".as_bytes()).expect("write failed");
   println!("file append success");
}


[変数の型を調べる]
fn type_of<T>(_: T) -> String{
  let a = std::any::type_name::<T>();
  return a.to_string();
}

fn main(){
    let a = String::from("String");
    let b = "str";
    let c = 123;
    let d = 123.4;
    
    println!("{}", type_of(&a));
    println!("{}", type_of(&b));
    println!("{}", type_of(&c));
    println!("{}", type_of(&d));
}

結果は次の通り
&alloc::string::String
&&str
&i32
&f64


[未使用の変数を表示しない]
#![allow(unused_variables)]


[first_word]

#![allow(unused_variables)]
fn main() {
    
    let s = String::from("hello world");
    fn first_word(s: &String) -> &str {
        let bytes = s.as_bytes();

        for (i, &item) in bytes.iter().enumerate() {
            if item == b' ' {
                return &s[0..i];
            }
        }

        &s[..]
    }
}


[日付関数 chrono の使用方法]
Cargo.toml入れてください:
[dependencies]
chrono = "0.4"

次に、これをクレートルートに入れます。
extern crate chrono;

サンプルプログラム
extern crate chrono;
use chrono::{Utc, Local, DateTime, Date};

fn main() {
    let utc_datetime: DateTime<Utc> = Utc::now();
    let utc_date: Date<Utc> = Utc::today();

    println!("{}", utc_datetime);
    println!("{}", utc_date);

    let local_datetime: DateTime<Local> = Local::now();
    let local_date: Date<Local> = Local::today();

    println!("{}", local_datetime);
    println!("{}", local_date);
}

実行結果
2020-06-26 11:28:55.222231200 UTC
2020-06-26UTC
2020-06-26 20:28:55.222231200 +09:00
2020-06-26+09:00


[文字列の加算]
    &str は文字列版のスライスである
    .as_slice() と
    .to_string() は交互に変換可能
    
    １文字足す
        c.push_str("a");
    文字列を足す
        c.push_str(&str);
        足す側が &str の場合、 + でも可能


[UTF8で文字列の長さを得る]
fn main(){
    let a: String = String::from("私はカカシ");
    let ll = a.chars().count();
    println!("len = {}",ll);
}

実行結果は
len = 5


[数字かアルファベットかを判断する]
fn main() { 
    println!("1 is a digit {}", '1'.is_digit(10)); 
    println!("f is a hex digit {}", 'f'.is_digit(16)); 
    println!("a is alphabetic {}", 'a'.is_alphabetic()); 
    println!("こis alphabetic {}", 'こ'.is_alphabetic()); 
    println!("a is alphanumeric {}", 'a'.is_alphanumeric()); 
    println!("1 is alphanumeric {}", '1'.is_alphanumeric()); 
} 

戻り値：

1 is a digit true 
f is a hex digit true 
a is alphabetic true 
こis alphabetic true 
a is alphanumeric true 
1 is alphanumeric true 

自作の関数
// 文字列が数字か否かを判定する 数字ならば true を返す
fn suuji_hantei (s: &String) -> bool {
    let mut x: bool = true;
    let i = s.len();
    if s.len() != s.chars().count() {
        x = false;
        return x;
    }
    if s.len() == 0 {
        x = false;
        return x;
    }
    let mut j: usize = 0;

    while j < i {
        if &s[j..j+1] < "0" || &s[j..j+1] > "9" {
            x = false;
        }
        j += 1;
    }
    x
}

fn main(){
    let c = String::from("321");
    
    println!("{}",suuji_hantei(&c));

}


[型変換]
rustはasで型を変換出来るのですが、数値から文字列の変換がasでは出来なかったので、
上手くいった方法を紹介します。
イマイチどういう方法が良いのかが分かっていません。
まずrustは文字列型がString &strの2種類存在するので,
String &strの変換を紹介したあと文字列から数値への変換を紹介します。

String → &str

&を付けるだけで出来ます。

    let str1: String = String::from("abc");
    let str2: &str = &str1;
    println!("{}", str2);  // "abc"

&str → String

to_string()を利用すると出来ます。

    let str1: &str = "abc";
    let str2: String = str1.to_string();
    println!("{}", str2);  // "abc"

String → num

.parse().unwrap()を利用すると出来ます。
ちゃんと変換後の型を指定しないと動きません。

    let stri: String = String::from("5");
    let num: i32 = stri.parse().unwrap();
    println!("{}", num);  // 5

&str → num

String → numと同じです。

    let stri = "5";
    let num: i32 = stri.parse().unwrap();
    println!("{}", num);  // 5

num → String

&str → Stringと同じくto_string()を利用すると出来ます。

    let num: i32 = 5;
    let stri: String = num.to_string();
    println!("{}", stri);  // "5"

追記
小数点の変換などの場合format!()を利用すると小数点の桁数とかを指定できるので、
format!()のが柔軟性が高いです。

    let num: f64 = 4.3 + 0.1;
    let strf1 = num.to_string();        // "4.3999999999999995"
    let strf2 = format!("{:.2}", num);  // "4.40"
    println!("{} {}", strf1, strf2);

num → &str

一旦Stringに変換してから&を付けます。
もっと良いやり方がある気がする。
num → &strは直接作れないのでこの方法で良いみたい。

    let num: i32 = 5;
    let stri: &str = &num.to_string();
    println!("{}", stri);  // "5"

char → num

asで数値に変換した後に48引きます。
ASCIIコードでいう'0'です。

    let c: char = '5';
    let num: i32 = c as i32 - 48;
    println!("{}", num);  // 5

num → char

from_digitでcharに変換します。
変換する数値はu32でないと行けないのでキャストします、基数は10進数なので10;
その後Some<T>の中身を取り出したいので.unwrap()しています。

    let num: i32 = 5;
    let c: char = std::char::from_digit(num as u32, 10).unwrap();
    println!("{}", c);  // '5'


[配列]
配列

    Rust の配列は固定長
    可変長配列は標準ライブラリの Vec<T> を使う
    要素の型を T とすると、配列の型は [T; size] となる
    size は配列の大きさ (データ型は usize)
    配列の宣言
        let 変数名: 配列の型 = [初期値; 大きさ];
        let 変数名: 配列の型 = [要素1, 要素2, ...];
    Rust には型推論があるので、左辺の配列の型は省略することができる
    Rust の場合、immutable で宣言された配列は要素の値を書き換えることができない
    要素の値を書き換えたい場合は let mut で宣言する
    要素のアクセスには角カッコ [ ] を使う
    添字は 0 から始まる
    配列の大きさは 変数名.len() で取得できる
    二次元配列のデータ型は [[T; row]; column] となる
    要素のアクセスは mat[x][y] のよう角カッコを 2 つ使う
    多次元配列も同じ方法で定義できる


[Copyトレイト コピートレイト]
#[derive(Debug,Copy,Clone)]
`derive` may only be applied to structs, enums and unions


[32を超える配列に文字列を代入する自作プログラム]
struct Himokux {
    himoku: String,
}
fn main(){
    let mut a:[&str;100] = [" ";100];
    
    let mut z = Himokux { himoku: String::new()};
    {
        let b: String = String::from("山田さん");
        println!("b = {}",b);
        z.himoku = b;
        a[1] = &z.himoku;
    }
    println!("a[1] = {}",a[1]);
}


[ライフタイム注釈記法 lifetime]
&i32        // a reference
            // (ただの)参照
&'a i32     // a reference with an explicit lifetime
            // 明示的なライフタイム付きの参照
&'a mut i32 // a mutable reference with an explicit lifetime
            // 明示的なライフタイム付きの可変参照
            
&strならば
&'a str
&'a mut str
となる

関数の使用例
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}


[変数名をアンダースコアで始める]
    変数名をアンダースコアから始めると、その変数が未使用でも警告が出ない。
    

[バイトリテラル表記 b"〇〇○" の意味]
fn main(){
    let a = "I am a boy";
    let c = b"You are a girl";
    println!("a = {}",a);
    println!("c = {:?}",c);
}
結果は
a = I am a boy
c = [89, 111, 117, 32, 97, 114, 101, 32, 97, 32, 103, 105, 114, 108]


[ファイルに追記する自作サンプル rinput.rs で作成した]
use std::fs::OpenOptions;
use std::io::{Write};
use std::result::Result;

// 入力したデータ1行をsuitou4UTF8.csvに追記する
fn add_line (fname: String, l_add: &str) -> Result<(), Box<std::error::Error>>{
    let mut file = OpenOptions::new()
        .write(true)
        .append(true)
        .open(&fname)
        .unwrap();

    writeln!(file, "{}",l_add)?;
    Ok(())
}


fn main(){
    let filename = String::from("/mnt/datadisk/USB_DATA/Temp/suitou1UTF8.csv");
// filename = filenames.maindata_filename
    let line_add = String::from("9047,2020/08/30,イースのガソリン,ガソリン,1299, 289.1(km) / 10.1(L) = 28.5 (km/L)");
    
    add_line (filename, &line_add);
    println!("書き込み終了");
    
}


[浮動小数点数を指定された桁数に丸める方法]
表示目的にのみ使用する場合は、formatting syntax built into println!()を
使用してください。
あなたがformat!() macroを使用し、文字列で丸めた数値を入れたい場合は

fn main() { 
    let x = 12.34567; 
    println!("{:.2}", x); 
} 

：たとえば、小数点以下2桁に丸められた番号を印刷する{:.2}書式指定子を
使用しています。

数字を四捨五入して別の数字に戻したい場合は、その数字に10の累乗を掛けて、
roundと入力し、同じ力で除算します。小数点以下2桁に丸めるために、これは、
12.34567 12.35000を印刷10 = 100

fn main() { 
    let x = 12.34567_f64; 
    let y = (x * 100.0).round()/100.0; 

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


[suitou4UTF8.csvの各行から費目のみを取り出す csvファイルを読み込んで配列に格納する]
use std::process::exit;
use std::io::{BufReader,BufRead}; 
use std::fs::File; 

// suitou4UTF8.csvの各行から費目のみを取り出す
fn get_item3<'a> (s: &'a str) -> &'a str{
    let bytes = s.as_bytes();
    let aa: &str;
    for(i,&item) in bytes.iter().enumerate() {
        if item == b',' {
            aa = &s[i+1..];
            return aa;
        }
    }
    println!("item 3 費目を取り出せませんでした");
    exit(0); 
}

fn main() { 
    // suitou4UTF8.csv を読み込んで、配列に格納する
    let mut himoku3: [&str;100] = [" ";100];
    let mut himoku3_no: usize = 0; // 登録されている費目の数
    let file = File::open("/mnt/datadisk/USB_DATA/Access/suitou4UTF8.csv").unwrap(); 
    let mut zz: String = String::new(); // 全費目を','で区切って1文にしたString
    
    // suitou4UTF8.csvを読み込んで zz に費目のみを ',' 区切りで格納する
    for line in BufReader::new(file).lines() { 
        if himoku3_no != 0 {
            let xx = get_item3(&line.unwrap()).to_string();
            zz.push_str(&xx);
            zz.push_str(",");
        }
        himoku3_no += 1;
        if himoku3_no > 98 {
            println!();
            println!("suitou4UTF8.csv に登録されている費目数が多すぎます。");
            println!();
            exit(0);
        }
        
    }
    himoku3_no -= 1;

    // zz を分解して、各費目を配列 himoku3[] に格納する
    let bytes = &zz.as_bytes();
    let mut hh: usize = 0;
    let mut jj: usize = 1;
    for(i, &item) in bytes.iter().enumerate(){
        if item == b',' {
            himoku3[jj] = &zz[hh..i];
            hh = i + 1;
            jj += 1;
        }
    }

} 


[入力された日付が範囲内にあるかどうかをチェックする。範囲外なら false を返す]
// 入力された日付が範囲内にあるかどうかをチェックする。範囲外なら false を返す
fn hiduke_check(st: String) -> bool {
    let mut r: bool = true;
    let bytes = &st.as_bytes();
    let mut hh: usize = 0;
    let mut jj: usize = 0;
    for(i, &item) in bytes.iter().enumerate(){
        if item == b'/' {
            if jj == 0 {
                let nen = &st[hh..i];
                let nen_num: i32 = nen.parse().unwrap();
                if (nen_num >= 2100) || (nen_num <= 1950) {
                    r = false;
                }
            }
            if jj == 1 {
                let tsuki = &st[hh..i];
                let tsuki_num: i32 = tsuki.parse().unwrap();
                if (tsuki_num >= 13) || (tsuki_num <= 0) {
                    r = false;
                }
                let nichi = &st[i + 1..];
                let nichi_num: i32 = nichi.parse().unwrap();
                if (nichi_num >= 32) || (nichi_num <= 0) {
                    r = false;
                }
            }

            hh = i + 1;
            jj += 1;
        }
    }
    r

}


[入力したデータ1行をsuitou4UTF8.csvに追記する]
// 入力したデータ1行をsuitou4UTF8.csvに追記する
fn add_line (fname: String, l_add: &str) -> Result<(), Box<dyn std::error::Error>>{
    let mut file = OpenOptions::new()
        .write(true)
        .append(true)
        .open(&fname)
        .unwrap();

    writeln!(file, "{}",l_add)?;
    println!("書き込み終了しました!!");
    Ok(())
}


[forの使い方]
n main(){
    let mut a: [&str;5] = ["";5];
    a[0] = "I am a boy";
    a[1] = "you are a girl";
    a[2] = "He is my friend";
    a[3] = "She is my favourite friend";
    a[4] = "They are people";
    let amax: usize = 5;
    
    for i in 0..amax {
        println!("{}",a[i]);
    }

}

結果
I am a boy
you are a girl
He is my friend
She is my favourite friend
They are people


[ベクタ]
サンプルコード
#![allow(unused_variables)]
fn main() {
    let mut v: Vec<&str> = Vec::new();
    {
        v.push("I am a boy");
        v.push("You are a girl");
    }
    println!("{}",v[0]);
    println!("{}",v[1]);
}
結果
I am a boy
You are a girl


#![allow(unused_variables)]
fn main() {
{
    let v = vec![1, 2, 3, 4];

    // vで作業をする

} // <- vはここでスコープを抜け、解放される
}

中身を読む方法2種類

#![allow(unused_variables)]
fn main() {
let v = vec![1, 2, 3, 4, 5];

let third: &i32 = &v[2];
let third: Option<&i32> = v.get(2);
}


[ファイルを読み取り文字列のベクタを取得する]
use std::{
    fs::File,
    io::{prelude::*, BufReader},
    path::Path,
};

fn lines_from_file(filename: impl AsRef<Path>) -> Vec<String> {
    let file = File::open(filename).expect("no such file");
    let buf = BufReader::new(file);
    buf.lines()
        .map(|l| l.expect("Could not parse line"))
        .collect()
}

// ---

fn main() {
    let lines = lines_from_file("/etc/hosts");
    for line in lines {
        println!("{:?}", line);
    }
}

失敗時にResultを返したい場合、必要に応じて実装を1行に縮小できます。
use std::{
    fs::File,
    io::{self, BufRead, BufReader},
    path::Path,
};

fn lines_from_file(filename: impl AsRef<Path>) -> io::Result<Vec<String>> {
    BufReader::new(File::open(filename)?).lines().collect()
}

// ---

fn main() {
    let lines = lines_from_file("/etc/hosts").expect("Could not load lines");
    for line in lines {
        println!("{:?}", line);
    }
}


[カレントディレクトリ dir を取得・表示・変更する]
use std::env;
use std::path::Path;

fn main() -> std::io::Result<()> {
    let path = env::current_dir()?;
    println!("starting dir: {}", path.display());

    let root = Path::new("/");
    assert!(env::set_current_dir(&root).is_ok());

    let path = env::current_dir()?;
    println!("final dir: {}", path.display());

    Ok(())
}

出力結果
$ rustc wd.rs && ./wd && rm wd
starting dir: /Users/wildmouse/hoge/wd
final dir: /


[dirリストを表示する]
use std::fs; 

fn main() { 
    let paths = fs::read_dir("/mnt/datadisk/USB_DATA/Access").unwrap(); 

    for path in paths { 
     println!("Name: {}", path.unwrap().path().display()) 
    } 
} 

出力
Name: /mnt/datadisk/USB_DATA/Access/ACCESSにEXCELファイルを読み込む注意.txt
Name: /mnt/datadisk/USB_DATA/Access/eventmemo.csv
Name: /mnt/datadisk/USB_DATA/Access/Obsolete
Name: /mnt/datadisk/USB_DATA/Access/pass.ods
Name: /mnt/datadisk/USB_DATA/Access/suitou1UTF8.csv
Name: /mnt/datadisk/USB_DATA/Access/suitou2UTF8.csv
Name: /mnt/datadisk/USB_DATA/Access/suitou4UTF8.csv
Name: /mnt/datadisk/USB_DATA/Access/suitoudata
Name: /mnt/datadisk/USB_DATA/Access/その他UTF8.csv
Name: /mnt/datadisk/USB_DATA/Access/カードUTF8.csv
Name: /mnt/datadisk/USB_DATA/Access/クロス集計.xlsx
Name: /mnt/datadisk/USB_DATA/Access/ゴミ箱UTF8.csv
Name: /mnt/datadisk/USB_DATA/Access/住所録.csv
Name: /mnt/datadisk/USB_DATA/Access/住所録.ods
Name: /mnt/datadisk/USB_DATA/Access/千葉大機械科.accdb
Name: /mnt/datadisk/USB_DATA/Access/技術資料
Name: /mnt/datadisk/USB_DATA/Access/花.accdb
Name: /mnt/datadisk/USB_DATA/Access/銀行UTF8.csv


[Rustでlsを書いた（ファイル一覧表示のみ） ]
use std::fs;

fn main() {
    let target = "./";
    let mut files: Vec<String> = Vec::new();
    for path in fs::read_dir(target).unwrap() {
        files.push(path.unwrap().path().display().to_string().replacen(target, "", 1))
    }

    files.sort();
    let strings = files.iter()
        .fold(String::new(), |joined, s| {
            if joined == String::new() { s.to_string() } else { joined + "  " + s }
        });

    println!("{}", strings)
}


[文字列の連結]
moveによる連結
一番標準の方法。わかりやすく効率も良いが、連結後はmoveによりhelloは使えなくなる。
fn by_moving() {
    let hello = "hello ".to_string();
    let world = "world";

    let hello_world = hello + world;

    println!("{}", hello_world);
}
helloはStringで、worldが&str。この2つを連結するとStringになるというのもよく
わかってない。（なんで to_string()が必要なの？）

cloneによる連結
clone()を使うことで、一時変数が作られ、それをmoveすることで文字列を連結している。
連結後もhelloが使えることがポイント。
fn by_cloning() {
    let hello = "hello".to_string();
    let world = "world";

    let hello_world = hello.clone()  + world;
    println!("{} ", hello_world);
}

mutingによる連結
helloをmutableで宣言して、push_strを使う方法。エレガントじゃないらしい。
fn by_mutating() {
    let mut hello = "hello".to_string();
    let world = "world";

    hello.push_str(world);
    println!("{} ", hello);
}


[文字列を大文字に変換する最も簡単な方法]
use std::ascii::AsciiExt; 

fn main() { 
    let r = "smash".to_ascii_uppercase(); 
    println!(" Hulk {:s}!", r); //Hulk SMASH! 

    //or one liner 
    println!(" Hulk {:s}!", "smash".to_ascii_uppercase()); 
} 

もう一つの方法
パッケージのインポートは必要ありません。
fn main() { 
    let test_str = "übercode"; //type &str 
    let test_string = test_str.to_string(); //type String 

    let uppercase_test_string = test_string.to_uppercase(); //type String 

    let uppercase_test_str = &*uppercase_test_string; //back to type &str 

    println!{"{}", test_str}; 
    println!{"{}", uppercase_test_string}; 
    println!{"{}", uppercase_test_str}; 
}


[文字列の最後の文字を取得する]
fn main() {
    let text = "[山田の案山子liefどうぞ]".to_string();
    let text_len = text.chars().count();
    let ss: String = text.chars().skip(text_len - 1).take(1).collect();
    println!("{}",ss);
}
skip()にはポジションを、take()には文字数を入力する。
結果
]


[文字列の文字数を取得する]
let s = String::from("ラウトは難しいです！"); 
s.chars().count();
これは10を返します。


[dependencies に記述するクレートのバージョンの求め方]
https://crates.io/crates/ここにクレートの名称を記入してネット検索する
例
https://crates.io/crates/colored

これで[dependencies]に
    colored = "2.0.0"
と記述できる


[文字に色を付ける]
use ansi_term::Colour;

fn main() {
    let enabled = ansi_term :: enable_ansi_support(); // Windowsでは必須
    eprintln!("{}", Colour::Red.paint("エラーが発生しましたよ"));
}

条件
　[dependencies]
　ansi_term = " 0.12.1 "


[環境変数の取得]
環境変数を取得するには標準ライブラリのstd::env::varを使います。
これは単体の値を取得する為のもので、すべてを取得したい場合はstd::env::varsです。

env::varは引数で渡された名前の環境変数があるかどうかをResultで返します。
ある場合はOk<String>、ない場合はErr<VarError>を返します。

例えばこのようなコードがあるとして、
use std::env;
fn main() {
  let var = env::var("VAR").expect("VAR is not defined");

  println!("{}", var);
}
単にcargo runするとエラー（thread 'main' panicked at 'VAR is not defined: NotPresent'）
になります。（$VARが設定されてない前提）
VAR=foo cargo runとちゃんと環境変数を設定して実行するとfooがプリントされます。

環境変数 %USERPROFILE% を実際に取得してみる
use std::env;
fn main() {
  let var = env::var("USERPROFILE").expect("VAR is not defined");

  println!("{}", var);
}
結果
t:\USB_DATA\rust\projects\trial>cargo run
   Compiling trial v0.1.0 (T:\USB_DATA\rust\projects\trial)
    Finished dev [unoptimized + debuginfo] target(s) in 0.49s
     Running `target\debug\trial.exe`
C:\Users\ishid

dotenv
dotenvというクレートを使うとそのプロジェクトだけの環境変数が使いやすくなります。
これはプロジェクトルートに.envというファイルを作り中に環境変数をまとめて書けば、
1行実行するだけでそれらを環境変数として扱えるクレートです。

使う前にCargo.tomlの依存に追加が必要です。
 [dependencies]
 dotenv = "0.15.0"

次に.envを以下のような感じで作ります。

VAR=foo
mainコードを書き換えます。

use std::env;
use dotenv::dotenv;

fn main() {
  dotenv().ok();

  let var = env::var("VAR").expect("VAR is not defined");

  println!("{}", var);
}
dotenv()の行で.envの中身をプログラム中だけ環境変数に追加します。よってこの実行は
コンソールにfooと表示します。

ちなみに.envが無くてもdotenv().ok()でエラーは特に起こらないようです。


