ぬの部屋(仮)
nu-no-he-ya
  • 1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • release,debug用のlibが混在しているときにPowerShellで分ける

    VTKをCMakeしたときにうっかり出力先を間違えて同じディレクトリにdebug,releaseが混在してしまったが、幸い名前が違っているので区別可能な場合、PowerShellを使ってそれらを区別する。

    なお、この手が使えるのは、vtkのlibファイル名が「機能名-バージョンd.lib」の構造をしているからなので、d.libで終わっていれば確実にデバッグ用だと判別できるから。

    1.名前一覧だけほしい場合

    デバッグ用

    デバッグファイルで末尾がdで終わるファイル名だけの一覧を取得

    Get-ChildItem -Path "d:/lib-files" -Recurse -Filter "*d.lib" | Select-Object -ExpandProperty Name
    
    vtkcgns-9.2d.lib
    vtkChartsCore-9.2d.lib
    vtkCommonColor-9.2d.lib
    vtkCommonComputationalGeometry-9.2d.lib
    vtkCommonCore-9.2d.lib
    vtkCommonDataModel-9.2d.lib
    vtkCommonExecutionModel-9.2d.lib
    vtkCommonMath-9.2d.lib
    vtkCommonMisc-9.2d.lib
    ....

    ただし、これだけなら普通のコマンドプロンプトでもできる。

    リリース用

    リリース版の拡張子を除くファイル名はdがつかないので、「d.libで終わらない」という指定が必要。これはPowerShellでなければできない。

    Get-ChildItem -Path "d:/lib-files" -Recurse | Where-Object { $_.Name -notlike "*d.lib" } | Select-Object -ExpandProperty Name
    

    2.ファイル群を別の場所にコピー

    上記の応用で、いっそ別の場所にコピーしてしまえる。今後のことを考えるとそのほうが楽。

    デバッグ用

    Get-ChildItem -Path "D:/lib-files" -Recurse -Filter "*d.lib" | ForEach-Object { Copy-Item -Path $_.FullName -Destination "d:/lib-debug" }
    

    これで、D:/lib-files/*.d.lib を d:/lib-debug/ にコピーする。

    リリース用

    Get-ChildItem -Path "D:/lib-files" -Recurse | Where-Object { $_.Name -notlike "*d.lib" } | ForEach-Object { Copy-Item -Path $_.FullName -Destination "D:/lib-release" }
    

    conda install しようとして CondaSSLError が出た場合の対処法

    anacondaでconda installしようとしたとき、以下のエラーが発生した。

    OpenSSLは入っているし、管理者権限でanaconda promptを動かしたりしても効果がなかった。

    (py29) C:\Users\myuser>conda install -c conda-forge -c open3d-admin open3d
    Collecting package metadata (current_repodata.json): failed
    
    CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is required to
    download and install packages.
    
    Exception: HTTPSConnectionPool(host='conda.anaconda.org', port=443): Max retries exceeded with url: /conda-forge/win-64/current_repodata.json (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available."))
      
    

    対策

     

    • anaconda3\library\bin\libcrypto-1_1-x64.dll
    • anaconda3\library\bin\libssl-1_1-x64.dll

    以下の二つを、

    anaconda3\DLLs\

    へコピーする。

    あとanaconda promptを再起動したほうがいいかもしれない。

    参考文献

    Rustのif let Someについて調べた話。

    Rustのif let some について(まとめ)。Rustのif let someがわからなかったので色々調べた。

    まず、Rustは至る所でコードレベルのパターンマッチが可能。

    Rustのパターンマッチングについて学んだ話


    次に、if letはmatch文のシンタクスシュガーである。
    従って、if letは=前後の値のパターンマッチと同時に、変数定義もできる

    Rustのパターンマッチングについて学んだ話 if let

    それで、some はenum Optionの、C++のunionでいうところのメンバ名である

    Rustのenumについて学んだ話(1) unionとしての使い方

    Rustのenumについて学んだ話(4) Optionはenumで実装されている

    従って、if let someは、
    ① if let 文でパターンマッチを行っている
    ② パターンマッチで、変数が、Option::Someのバリアントを持っているをチェック
    ③ パターンマッチの機能で、変数を定義

    という視点で捉えられる。

    マッチだが、retはOption型なので、これは定数Noneか、Some(値)のどちらかが入っている。if letで「retはSome(v)という形の値が入っているか」をチェックする。そしてもしマッチするなら、変数vを定義し、そこに値を入れる。これは正規表現で、パターンにマッチする文字列を取得するのに似ている。

    感想

    if let Some は、ifの隣に変数定義に使うletが出てくる上に、未知の関数のように見えるSome()の中にそれまで定義されていなかった変数が突如出現するので、Rust初学者にとってはかなりわかりにくい文法だと思う。

    Rustのenumについて学んだ話(4) Optionはenumで実装されている

    Optionに該当する者は比較的新しいC++でも実装されている。std::optionalとstd::nulloptがそれにあたる。ともあれ、Optionは、戻り値にその関数が本来返す値の他に、値が存在しないことを示すNoneを返すことができるようにする仕組みである。

    値が存在しないというのは、例えば「i32の配列の中に条件を満たす値があったら返す」のような処理で、該当する数値がなかった場合は、答えがないことになる。

    自前実装版

    以下は、値がないことも表せる値をValueOrNotFoundというenumで自前実装した例。

    // Optionのまねごとをするために自前実装した、
    // 「値がないことを表せる ValueOrNotFound型」
    enum ValueOrNotFound{
      Value(i32),  // i32型のValue
      NotFound,    // 定数 NotFound。結果が見つからなかったときはこれが有効
    }
    
          
    // src中の、最初に見つかったthres以下の値を返す関数
    // 戻り値はValueOrNotFound型で返す。これは整数値かNotFound定数のどちらかを入れられる
    fn Search(src:[i32;5],thres:i32)->ValueOrNotFound{
    
      for &val in src.iter(){
        if val <= thres{
    
          return ValueOrNotFound::Value(val); // 見つかった場合、整数値を返す
    
        }
      }
    
      return ValueOrNotFound::NotFound; // 見つからない場合、NotFound定数を返す
    
    }
    
          
    
    fn main() {
    
      // 配列を定義
      let array = [5,6,7,8,9];
    
      // ある値以下の値を一つ返す
      let ret = Search(array,3);
    
      // 値が入っていたら、vを定義しそれを代入
      if let ValueOrNotFound::Value(v) = ret {
        println!("found {}",v);
      }
      else{
        println!("not found");
      }
    
    }
    

    Optionを使った例

    // src中の、最初に見つかったthres以下の値を返す関数
    // 戻り値はOption型で返す。これはジェネリックで指定するi32型を取る
    /*
     Optionの定義は以下のようになっている。
     <T>とジェネリックで型を指定するようになっているのであらゆる型を持てる。
    pub enum Option<T> {
        /// No value.
        None,
        /// Some value of type `T`.
        Some(T),
    }
    */
    
    fn Search(src:[i32;5],thres:i32)->Option<i32>{
    
      for &val in src.iter(){
        if val <= thres{
    
          return Option::Some(val); // 見つかった場合、整数値を返す
    
        }
      }
    
      return Option::None; // 見つからない場合、Noneを返す
    
    }
    
    
    fn main() {
    
      // 配列を定義
      let array = [5,6,7,8,9];
    
      // ある値以下の値を一つ返す
      let ret = Search(array,3);
    
      // 値が入っていたら、vを定義しそれを代入
      if let Option::Some(v) = ret {
        println!("found {}",v);
      }
      else{
        println!("not found");
      }
    
    }
    

    Rustのenumについて学んだ話(3) 混ぜて使う

    enumにはCのunion的な使い方とCのenum的な使い方の両方があるということが分かったが、これを混ぜて使うことも多い。

    // 色を表現する構造体 RGB
    #[derive(Copy,Clone,PartialEq)]
    struct RGB{
      r:i32,g:i32,b:i32
    }
    impl RGB{
      fn New(R:i32,G:i32,B:i32)->RGB{return RGB{r:R,g:G,b:B};}
    }
    
    //////////////////////////////////////////////////
    
    // 色を表現する構造体 HSV
    #[derive(Copy,Clone,PartialEq)]
    struct HSV{
      h:f32,s:f32,v:f32
    }
    impl HSV{
      fn New(H:f32,S:f32,V:f32)->HSV{return HSV{h:H,s:S,v:V};}
    }
    //////////////////////////////////////////////////
    
    
    // 画像のピクセルを入れる型
    // RGBの任意の値、HSVの任意の値 に加え、定数Invalid のどれかを入れることができる
    // Invalid(i32) と書き直すと少し理解がし易いが、入るのはInvalid一つだけなので意味的には違う
    //        (概念的にはInvalidがたまたまi32にキャストできるだけで、i32を入れられるわけではないので)
    #[derive(Copy,Clone,PartialEq)]
    enum PixelInfo{
      ColorRGB(RGB),    // RGBを入れる場合 RGB型の変数ColorRGB
      ColorHSV(HSV),    // HSVを入れる場合 HSV型の変数ColorHSV
      Invalid,          // 定数を定義  RGBが無効のときはこれを入れておく事
    }
    //////////////////////////////////////////////////
    
    fn main() {
    
      let mut pixel:PixelInfo;
    
      // ピクセルを使うかどうかを決める
      let unuse:bool = false;
    
      if unuse {
        // 使わないときはInvalidを入れておく
        pixel = PixelInfo::Invalid;
      }
      else{
        // 色を指定
        pixel = 
          PixelInfo::ColorRGB(
            RGB::New(
              255,
              0,
              0,
            )
          );
    
      }
    
    
    
      if pixel == PixelInfo::Invalid{
        // ピクセルが無効なら対応した処理を行う
        println!("the pixel is invalid");
      }
      else if let PixelInfo::ColorHSV(c) = pixel{
        // ピクセルが有効ならパターンマッチでcを定義して色を取得
        println!("color HSV = ({} {} {})",c.h,c.s,c.v);
      }
      else if let PixelInfo::ColorRGB(c) = pixel{
        // ピクセルが有効ならパターンマッチでcを定義して色を取得
        println!("color RGB = ({} {} {})",c.r,c.g,c.b);
      }
    
    }
    

    C++で似たようなコードを書くと、たぶん以下のようになる。

    #include <iostream>
    
    struct RGB {int r, g, b;};
    struct HSV {float h,s,v; };
    
    union PixelInfo {
      RGB rgb;
      HSV hsv;
    
      // この定数も取れるようにする
      enum {
        INVALID,
      }Invalid;
    };
    
    int main()
    {
      PixelInfo pi;
    
      pi.rgb = { 255, 255, 255 }; // 他の物を入れると無効になる
    
      pi.Invalid = PixelInfo::INVALID;
    
      std::cout << pi.Invalid;
    }
    

    [速報]CLaunchとVisual C++の相性問題が解決したかもしれない話

    ぴょんきち 氏が開発、公開しているCLaunch。

    http://hp.vector.co.jp/authors/VA018351/claunch.html

    どうやら2023/08/11に最新バージョン4.05がリリースされた模様。

    http://hp.vector.co.jp/authors/VA018351/whatsnew.html

    以前、VC++との相性がやたらと悪いという話をした

    のだが、五日間ほどVC++2022,Win32APIの開発時に併用してみたところ、一度も問題が起こらなかったので、解決しているのかもしれない。元々再現性100%ではないので断言できないのだが、間違いないとすればこれは朗報。ありがとうございます。

    Rustのenumについて学んだ話(2) Cのenumとしての使い方

    Rustのenumは高機能なunionという話が前回で、それとは別に、C/C++のenumのような使い方もできる。

    // Rust の enum は、C言語のenumのように特定の値を持つ定数のみを取れる型を定義するように使用できる。
    // ただし、指定できるのは整数のみで、f32やstring等は不可
    enum AsciiCode{
      AsciiA = 65,
      AsciiB = 66,
      AsciiC = 67,
    }
    
    
    fn main() {
    
      // cu を定義。入れられるのはAsciiA,B,Cのいずれかのみ
      let mut cu:AsciiCode = AsciiCode::AsciiA;
    
      cu = AsciiCode::AsciiB;
    
      // この場合もパターンマッチで比較する
      if let AsciiCode::AsciiA=cu{
        println!("AsciiA is used." );
      }
      else{
        println!("Not A." );    
      }
    
      // 数値を取り出すときは as をつける
      println!("cu is {}",cu as i32);
    
    }
    

    なお、変数同士を比較するには、==を使うが、デフォルトでは実装されていないので、PartialEqを指定する。

    // 変数同士を比較するときは、==を使うためにPartialEqを指定
    #[derive(PartialEq)]
    enum AsciiCode{
      AsciiA = 65,
      AsciiB = 66,
      AsciiC = 67,
    }
    
    
    fn main() {
    
      // cu を定義。入れられるのはAsciiA,B,Cのいずれかのみ
      let cu:AsciiCode = AsciiCode::AsciiA;
    
      let rs:AsciiCode=AsciiCode::AsciiB;
    
      // == で比較できる
      if rs == cu{
        println!("same");
      }
      else{
        println!("not same");
      }
    
    }
    

    注意点として、この記法 enum TYPE{ NAME= 65, } で指定できるのは整数のみで、f32などは入れられない。どうもこの表記自体はenumの本来の使い方としてはややずれているようで、Cなどのほかの言語との歩調を合わせるのがこの表記法が可能な主な理由だという(話があった)。

    なお、数値を指定しなくても使える。as i32すれば整数にもなるが、あまりこれを前提としたコードを書くべきとは思えない。

    // 型も値も指定しないバリアントを持てる。
    // ==を使うためにPartialEqを指定
    // as i32をするとmoveされてしまうのでCopyも指定。CopyのためにCloneも指定。
    #[derive(Copy,Clone,PartialEq)]
    enum AsciiCode{
      AsciiA,
      AsciiB,
      AsciiC,
    }
    
    
    fn main() {
    
    
      println!("A as int {}",AsciiCode::AsciiA as i32);
      println!("B as int {}",AsciiCode::AsciiB as i32);
      println!("C as int {}",AsciiCode::AsciiC as i32);
    
      // cu,rs を定義。入れられるのはAsciiA,B,Cのいずれかのみ
      let cu:AsciiCode = AsciiCode::AsciiA;
      let rs:AsciiCode = AsciiCode::AsciiB;
    
      // == で比較した例
      if rs == cu{
        println!("same");
      }
      else{
        println!("not same {} vs {}",cu as i32,rs as i32);
      }
    
    }
    
    A as int 0
    B as int 1
    C as int 2
    not same 0 1

    Rustのenumについて学んだ話(1) unionとしての使い方

    Rustのenumには三つの使い方がある。

    まずはC言語におけるunionに近い使い方。

    以下ではC_Union_Like型を定義しているが、この変数はi32,f32,Stringの「いずれか一つ」を代入することができる。

    // Rust の enum は、C言語のunionに近い使い方ができる。
    // 以下ではivalue,fvalue,svalueの三つのバリアントを定義しているが、
    // 一度に有効なのは一つだけ。
    enum C_Union_Like{
      ivalue(i32),
      fvalue(f32),
      svalue(String),
    }
          
          
    fn main() {
    
      // C_Union_Likeのivalueにi32を入れる。
      let mut cu:C_Union_Like = C_Union_Like::ivalue(33);
    
      // fvalueに入れたので、cuはf32を持つようになった
      cu = C_Union_Like::fvalue(7.5);
    
      // svalueに入れたので、cuはStringを持つようになった
      cu = C_Union_Like::svalue("hello".to_string());
    
    
      // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。
      // cu がどの値を持っているかを知る方法は
      // パターンマッチングでマッチするかで判断する
    
      // cu が ivalue にマッチするなら、iiを定義し、ivalueの値を代入
      if let C_Union_Like::ivalue(ii)=cu {
        println!("int is used. {}",ii);
      }
      else if let C_Union_Like::fvalue(ff)=cu{
        println!("float is used. {}",ff);
      }
      else if let C_Union_Like::svalue(ss)=cu{
        println!("String is used. {}",ss);    
      }
    
    }
    

    このプログラムは、C/C++における以下に近い。

    struct C_Union_Like {
    
        int type;
        union {
            int ivalue;
            float fvalue;
            //std::string svalue; // これはC++ではできないが、Rustならできる
        };
    };
    
    
    int main()
    {
    
        C_Union_Like cu;
    
        cu.type = 0;
        cu.ivalue = 33;
    
        cu.type = 1;
        cu.fvalue = 7.5f;
    
        switch (cu.type) {
        case 0:
            printf("int is used. %d \n", cu.ivalue);
            break;
        case 1:
            printf("float is used. %d \n", cu.fvalue);
            break;
        }
    
    }
    

    Rustのenumは、C/C++のunionと違ってStringなどの複雑な型を取ることができる。さらに型情報も自動で持つので、unionのように自分で管理する必要がない。注意点として、今何が入っているかはパターンマッチングで判断する。上ではif letを使っているが、matchを使ってもよい。

    fn main() {
    
      // C_Union_Likeのivalueにi32を入れる。
      let mut cu:C_Union_Like = C_Union_Like::ivalue(33);
    
      // svalueに入れたので、cuはStringを持つようになった
      cu = C_Union_Like::svalue("hello".to_string());
    
      // fvalueに入れたので、cuはf32を持つようになった
      cu = C_Union_Like::fvalue(7.5);
    
    
    
      // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。
      // cu がどの値を持っているかを知る方法は
      // パターンマッチングでマッチするかで判断する
    
      // cuの取りうるバリアントが多い場合はmatchのほうが読みやすい
      match cu{
        C_Union_Like::ivalue(ii) => {
          println!("int is used. {}",ii);
        },
        C_Union_Like::fvalue(ff) => {
          println!("float is used. {}",ff);
        },
        C_Union_Like::svalue(ss) => {
          println!("String is used. {}",ss);
        },
        _ =>{}
      }
    
    }
    

    Rustのパターンマッチングについて学んだ話 if let

    if let文について。

    端的にいうと、

    • if ... 式が true か false か で分岐を行う
    • if let ... パターンがマッチするか/しないか で分岐を行う

     

    fn main() {
    
      let mytuple=(3,4,5);
    
    
      // (3,4,何でもいい) というタプルと (3,4,5) というタプルはマッチするので
      // if節が実行される
      if let (3,4,_) = mytuple{
        println!("mached ");
      }
    
    
      // (3 ,second, 何でもいい) というタプルと、(3,4,5)はマッチするので
      // secondが定義されて、mytuple.1 が代入される
      if let (3,second,_) = mytuple{
    
        println!("second element is {} ",second);
      }
      
    
      // (4,second,何でもいい) というタプルは、(3,4,5)とマッチしないので、
      // else 節へ行く
      if let (4,second,_) = mytuple{
    
        println!("second element is {}",second);
    
      }
      else {
    
        println!("not matched");
    
      }
    
    
    }
    

    if let はパターンマッチで分岐するので、match文に近い。matchが複数のパターンと比較するが、比較の対象が一つだけの時は書きやすいようにif letが用意されている。

    あと、if letには網羅性がない。matchは網羅性があるので、必要なパターンを陳列し終わったら、「そのほかのケース」として_ を用意し、match文に用意された選択肢のどれか一つに必ずマッチするように書かなければならないが、ifはそうではない。

    fn main() {
    
      let mytuple=(3,4,5);
    
    
    
      // mytuple と (3,second,_)  のマッチ
      match mytuple{
        (3,second,_)=>println!("first = 3, second = {}",second),
        _ => (),
      }
    
      // mytuple と (3,second,_)  のマッチ。
      // 比較対象が一つだけならif letのほうが直観的
      if let (3,second,_) = mytuple{
        println!("first = 3, second = {}",second);
      }
    
    }
    

    Rustのパターンマッチングについて学んだ話

    Rustは構文のレベルでパターンマッチングをする言語で、しかも至る所でそれが出てくるので、パターンマッチングを受け入れないとコードを読めるようにならない。

    例えばmatch文。

    fn main() {
    
        let x:i32=5;
        let y:i32=10;
    
        // 「(5 , 10) というパターン」
        match (x,y){
    
            // (5,10) の内容が 「(5,10)」 に一致する場合
            (5,10)=> println!("Both x and y are 5 and 10, respectively."),
    
            // (5,10) の内容が 「(5,何でもいい)」 に一致する場合
            (5,_)=>  println!("x is 5, and y can be any value."),
    
            // (5,10) の内容が 「上記のパターン以外」 に一致する場合
            _ =>     println!("Neither of the above patterns match x and y."),
        }
    
    
        print!("{} {}",x,y);
    
    }
    

    これはなんとなくわかる。

    ところがRustには「パターンにマッチするか」だけではなく、「マッチして、それが変数だったらそこに値を拘束する」という機能もある。

    つまり以下は、

    ・「パターンマッチ」

    ・「value_of_yの変数宣言」

    ・「value_of_yへのyの代入」

    が同時に行われている。

    fn main() {
    
        let x:i32=5;
        let y:i32=7;
    
        // 「(5 , 10) というパターン」
        match (x,y){
    
            (5,10)=> println!("Both x and y are 5 and 10, respectively."),
    
            // パターンマッチングを行い、マッチした場合は値の拘束(変数の定義と代入)も行う
            (5,value_of_y )=>  println!("x is 5, and y is {}",value_of_y),
    
            _ =>     println!("Neither of the above patterns match x and y."),
        }
    
    }
    

    一事が万事この調子なので、変数を定義する機能だと思っていたletも、実はパターンマッチと、マッチした場合の値の拘束を同時に行う構文だということになる。

    だからlet文で変数定義をするときに_ (ワイルドカード)が使えてしまう。

    fn main() {
    
        // 例1
        // (x,y)というパターンと(3,5)はマッチする
        // マッチするので、
        // x に 3 を拘束
        // y に 5 を拘束
        // この二つを同時に行う。
        let (x,y)=(3,5);
    
    
        // 例2
        // (z,何でもいい) というパターンと (7,9) はマッチする
        // マッチするから 7 が z に 拘束される
        // _ はワイルドカードなので無視される。
        let (z,_)=(7,9);
    
        println!("{} {} {} ",x,y,z);
    
    }
    

    let文の=の右辺と左辺でパターンマッチを行い、拘束可能な部分は拘束する。拘束できないところは無視する。

    こんなもの何に使うんだと思うのだが、ある構造体なりタプルかなりから値を取り出したい、しかし全部取り出す必要はないときに、不要な変数宣言を省略できるという利点がある。

    fn main() {
    
        // 三つの三次元座標を用いて三角形を一枚定義
        let triangle_points = [
             (0,3,9), // 頂点1
             (7,0,6), // 頂点2
             (4,7,2)  // 頂点3
        ];
    
        // この三角形を Z 平面に投影した二次元座標を取得したい
        for p in triangle_points{
    
            // 三要素の p から前二つだけ取り出し、x,yに拘束
            // 三つ目の要素は z に入れるべきだが、不要なので _ を指定して省略。つまり変数 z は定義しない。
            let (x,y,_) = p;
    
            println!("{} {}",x,y);
    
        }
    
    }
    

    Rust的には、「比較するものとされるものがマッチするならコンパイルが通る」わけで、当然構造体でも同じ理屈が通用する。

    構造体の場合、無視の記号は .. を用いる。また構造体はフィールド名で値を選択するので、順番は気にしなくていい。

    struct Point {
        x: i32,
        y: i32,
        z: i32,
    }
    
    fn main() {
    
    
      let point = Point { x: 0, y: 7, z: 9 };
    
      // point からy座標だけ取り出したいので
      // y_coord変数を定義し、 point.y を拘束
      // .. により、ほかのフィールドは無視する
      let Point { y:y_coord, .. } = point;
    
      // point.y が取れているか確認
      println!("y value is {}",y_coord);
    
    
    }