VTKをCMakeしたときにうっかり出力先を間違えて同じディレクトリにdebug,releaseが混在してしまったが、幸い名前が違っているので区別可能な場合、PowerShellを使ってそれらを区別する。
なお、この手が使えるのは、vtkのlibファイル名が「機能名-バージョンd.lib」の構造をしているからなので、d.libで終わっていれば確実にデバッグ用だと判別できるから。
デバッグファイルで末尾がdで終わるファイル名だけの一覧を取得
Get-ChildItem -Path "d:/lib-files" -Recurse -Filter "*d.lib" | Select-Object -ExpandProperty Name
ただし、これだけなら普通のコマンドプロンプトでもできる。
リリース版の拡張子を除くファイル名はdがつかないので、「d.libで終わらない」という指定が必要。これはPowerShellでなければできない。
Get-ChildItem -Path "d:/lib-files" -Recurse | Where-Object { $_.Name -notlike "*d.lib" } | Select-Object -ExpandProperty Name
上記の応用で、いっそ別の場所にコピーしてしまえる。今後のことを考えるとそのほうが楽。
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" }
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."))
以下の二つを、
へコピーする。
あとanaconda promptを再起動したほうがいいかもしれない。
Rustのif let some について(まとめ)。Rustのif let someがわからなかったので色々調べた。
まず、Rustは至る所でコードレベルのパターンマッチが可能。
次に、if letはmatch文のシンタクスシュガーである。
従って、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初学者にとってはかなりわかりにくい文法だと思う。
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"); } }
// 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"); } }
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。
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は高機能な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); } }
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); }, _ =>{} } }
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は構文のレベルでパターンマッチングをする言語で、しかも至る所でそれが出てくるので、パターンマッチングを受け入れないとコードを読めるようにならない。
例えば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); }