削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎分岐: Rust は、ifmatch の2つの分岐構文を持ちます。 // 条件式に整数を使うと -> コンパイルエラー
タグ: 2017年版ソースエディター
383 行
 
=== 分岐 ===
Rust は、[[#if|if]] と [[#match|match]] の2つの分岐構文を持ちます。
;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a20747fbf03fa8568255ca1225c1ec19 if.rs]:<syntaxhighlight lang=rust>
 
fn main() {
==== if ====
let number = 3;
ifは、条件式に基づき分岐し、分岐先の式を評価します。
ifの値は、分岐先の式の値です。
elseを省略し条件式が偽であった場合のifの値は <code>()</code> です。
 
;構文:<syntaxhighlight lang=ebnf>
if number < 5 {
if-expr := if 条件式 '{' 式1 '}' [ else '{' 式2 ] '}'
println!("条件は真でした");
} else {
println!("条件は偽でした");
}
println!(
"条件は{}でした",
"偽真".chars().nth((number < 5) as usize).unwrap()
);
}
</syntaxhighlight>
:;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=84117443c135c52137b9005717322e82 条件式に整数を使うと]:<syntaxhighlight lang=Rust line>
;実行結果:<syntaxhighlight lang=text>
条件は真でした
条件は真でした
</syntaxhighlight>
: C言語なら<syntaxhighlight lang=c inline>"偽真"[number < 5]</syntaxhighlight>で済むところですが、str はインデックスによるアクセスができず、boolは暗黙にはusizeに変換されないので、こうなりました。
: それはともかく、Rust の '''if''' は条件式がカッコ ( ) で括らなくてもいい以外は、C言語系と同じですが、、、
 
==== if 文 ====
条件分岐は、条件式に括弧<code>()</code>が不要<code>-h</code>などC言語と違うが、基本的な仕組み・概念はC言語などと同じである。
 
;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c2f542b8f7ff8437d81c3e653b88cff2 if-as-stmt.rs]:<syntaxhighlight lang="rust" line>
fn main() {
let numberi = 30;
let mut msg = "偽"; // 出力文字用の変数.
if i {
 
if number < 5 {println!("zero");
msg = "真";
}
println!("条件は{}でした", msg);
}
</syntaxhighlight>
:;実行結果コンパイルエラー:<syntaxhighlight lang=text>
error[E0308]: mismatched types
条件は真でした
--> src/main.rs:4:8
|
4 | if i {
| ^ expected `bool`, found integer
 
For more information about this error, try `rustc --explain E0308`.
</syntaxhighlight>
:: Rustでは、ifに限らず、条件式は、bool 型でなければいけません。
 
;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2c8960df447a87aaeaecced963d20cde if.rs]:<syntaxhighlight lang=rust line>
==== if 式 ====
ifは文のほか、値を返す「式」としての構文も持ちます。
 
;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=daccd9877dcbe53c9e4d1dbe7eeea347 if-as-expr.rs]:<syntaxhighlight lang=rust highlight="4,5,7,8" line>
fn main() {
let numberi = 30;
 
letif msgi == if number < 50 {
println!("");
} else {
println!("非零");
}
let s = if i == 0 {
"ゼロ"
} else {
"非ゼロ"
};
println!("条件は{}でした", msgs);
}
 
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text>
条件は真でした
ゼロ
</syntaxhighlight>
:気をつけたいのは、式の値が参照されるifでは、それぞれの式(ここでは <code>"ゼロ"</code> と <code>"非ゼロ"</code>)にセミコロン<code> ; </code>を付けてはいけない点です。
:変数宣言の初期化項にif式を使っています。
:: もし セミコロン<code> ; </code> をつけると、ブロックの値は、Unit 型 <code>()</code> になります。
::Rustの '''if式''' は、[[C言語]]の三項演算子<syntaxhighlight lang=c inline>式 ? 値1 : 値2</syntaxhighlight>や、[[Python]]のif式<syntaxhighlight lang=c inline>値1 if 式 else 値2</syntaxhighlight>のように値を持ちます。
:: ifの、分岐先の2つの式の型は同じでなければいけません。
:気をつけたいのは、if式では、 <code>"真"</code> と <code>"偽"</code> とセミコロン<code> ; </code>を付けてはいけない点です。
:: else節が省略された場合は、Unit 型を返さなければいけません。
:: もし セミコロン<code> ; </code> をつけると、ブロックの値は、単位ユニット <code>()</code> になります。
::: 式の最後に、セミコロン<code>};</code> が必要ということです<ref>C言語系では、式を文にする為いに<code>};</code> が必要です。Rustもそう説明されている場合がありますが、Rustでは式の型の一致が目的です。<ref>。
:また、<syntaxhighlight lang=rust inline>let msg = </syntaxhighlight>の文末の<code>};</code> のセミコロンも忘れがちです。
:また、<syntaxhighlight lang=rust inline>let s = if i == 0 {</syntaxhighlight>の文末の<code>};</code> のセミコロンも忘れがちです。
Rust では if に限らず、コードブロックは式の一種で値を返します<ref>コードブロックが値を持つプログラミング言語としては、BCPLや[[Ruby]]があります。</ref>。その場合、コードブロックの最後の式がコードブロックの値となりセミコロン<code> ; </code>は不要で、もし、<code> ; </code>をつけると<code> ; </code>の次の式(=空文)の値<code> () </code>がコードブロックの値になります。
:Rust では if に限らず、コードブロックは式の一種で値を返します<ref>コードブロックが値を持つプログラミング言語としては、BCPLや[[Ruby]]があります。</ref>。その場合、コードブロックの最後の式がコードブロックの値となりセミコロン<code> ; </code>は不要で、もし、<code> ; </code>をつけると<code> ; </code>の次の式(=空文)の値<code> () </code>がコードブロックの値になります。
 
この特徴は、関数型プログラミングを意識したものですが、同時に後に説明する所有権の移譲で重要な役割を果たします。
453 ⟶ 449行目:
Rustでは、C言語のNULLに相当する値は None です。
通常の変数は None の代入は受付けませんが、Some() を使うと None を取り得る変数が宣言できます<ref>[https://doc.rust-lang.org/stable/std/option/enum.Option.html Option in std::option - Rust]<</ref>。
;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=afb9193c50a316090b6e3119f994f8cf some.rs]:<syntaxhighlight lang=rust line>
fn main() {
let mut x = Some(0);
512 ⟶ 508行目:
 
==== match ====
matchは、パターンに基づき分岐し、分岐先の式を評価します。
C言語でいうswitch式は無い。代わりに rust には match 式がある。
matchの値は、分岐先の式の値です。
 
matchは、C言語でいうswitch case 文と似ていますが、switch文は式とリテラルの値の一致を上から順に検査しますが、matchでは式がパターンに適合するかを上から順に検査します。
kaki下記コードは、[https://doc.rust-jp.rs/rust-by-example-ja/flow_control/match.html Rust 日本語ドキュメント] のサンプルコードをもとに、英語や課題などの情報を除いたものである。
また、whenはbreakが必要ありません(フォールスルーしません)。
 
;構文:<syntaxhighlight lang=rust style="width:40em"ebnf>
match-expr := match 式 '{'
パターン1 '=>' 式1 ,
パターン2 '=>' 式2 ,
パターンn '=>' 式n ,
変数 '=>' どのパターンにもマッチしなかった場合の式 ,
'}'
</syntaxhighlight>
: パターンと式を '=>' で繋いだものをアームといいます。
: パターンが変数だとあらゆる値にマッチし、式の値が束縛されます。典型的には、<code>_</code> アンダースコアで、これは値を束縛しないワイルドカードパターンです。
: パターンは網羅する必要があるので、最後のアームのパターンをワイルドカードを置く事が多いですが、例えば bool 型の値ならば flase と true の2つのパターンで網羅できるのでワイルドカードをパターンとするアームは不要です(コンパイル時に warning になります)。
 
下記コードは、[https://doc.rust-jp.rs/rust-by-example-ja/flow_control/match.html Rust 日本語ドキュメント] のサンプルコードをもとに、英語や課題などの情報を除いたものです。
;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=36834ebbee0d26d6b2374469cf98664e コード例]:<syntaxhighlight lang=rust line>
fn main() {
let number = 13;
531 ⟶ 543行目:
13..=19 => println!("A teen"),
 
// その他の場合の処理
_ => println!("Ain't special"),
}
 
let boolean = true;
// マッチは式でもある。
let binary = match boolean {
false => 0,
true => 1,
// _ => 2, // !!! note: `#[warn(unreachable_patterns)]` on by default !!!
};
 
println!("{} -> {}", boolean, binary);
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang=text style="width:40em">
Tell me about 13
A teen
true -> 1
</syntaxhighlight>
 
 
基本的な使い方は、switch文や他言語のmatchと同じである。他言語を知らない人のために構文を提示すると、
 
<syntaxhighlight lang=rust style="width:40em">
match 式 {
アーム1 => その条件が満たされた場合の処理1 ,
アーム2 => その条件が満たされた場合の処理2 ,
アームn => その条件が満たされた場合の処理n ,
 
// アンダーラインは上記のどの条件も満たされなかった場合の処理
_ => どの条件も満たされなかった場合の処理,
}
</syntaxhighlight>
: <code>_</code> アンダースコアは、あらゆる値にマッチし、値を束縛しないワイルドカードパターンです。
 
=== 反復 ===