削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
→‎制御構造: Crystalの実情に合わせて変更
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎型による分岐: when 節が式ではなく型であった場合、caseの式を <code>is_a?</code> で評価し、最初に一致した when に対応する式が実行されます。
タグ: 2017年版ソースエディター
447 行
</syntaxhighlight>
 
= https://ja.wikibooks.org/w/index.php?title=Ruby&oldid=205564#%E5%88%B6%E5%BE%A1%E6%A7%8B%E9%80%A0 から移入 =
== 制御構造 ==
'''[[w:制御構造|制御構造]]'''(せいぎょこうぞう、''control flow'')とは、「順次」「分岐」「反復」という基本的な処理のことを言います。
490 ⟶ 489行目:
)
</syntaxhighlight>
;表示実行結果:<syntaxhighlight lang="text">
NaN
(if a < 0
519 ⟶ 518行目:
puts "nは1" if n == 1
</syntaxhighlight>
;表示実行結果:<syntaxhighlight lang="text">
nは0
</syntaxhighlight>
535 ⟶ 534行目:
end
</syntaxhighlight>
;表示実行結果:<syntaxhighlight lang="text">
Non-zero
</syntaxhighlight>
550 ⟶ 549行目:
puts "nは1" unless n == 1
</syntaxhighlight>
;表示実行結果:<syntaxhighlight lang="text">
nは1ではない
</syntaxhighlight>
584 ⟶ 583行目:
)
</syntaxhighlight>
;表示実行結果:<syntaxhighlight lang="text">
two
(case n
598 ⟶ 597行目:
:C言語系のswitch文に慣れた人はbreakがないことに気がつくと思います。Crystalのcaseはfall throughしませんし、fall throughさせる方法もありません。
 
===== when節が定数でなく式を受付ける事を使ったトリックます =====
[[#if|if]]を使ったコードをcaseに書き換えてみましょう。
 
;case true トリックの式の省略:<syntaxhighlight lang=crystal line>
a = 0.0 / 0.0
case true
when a < 0
puts "minus"
628 ⟶ 627行目:
)
</syntaxhighlight>
;表示実行結果:<syntaxhighlight lang="text">
NaN
(case true
641 ⟶ 640行目:
end) # => NaN
</syntaxhighlight>
このコードは when 節の式の値とcaseの式を <code>===</code> で比較し、最初に一致した when に対応するが実行される事を利用しています。
 
===== 型による分岐 =====
when 節が式ではなく型であった場合、caseの式を <code>is_a?</code> で評価し、最初に一致した when に対応する式が実行されます。
 
;型による分岐:<syntaxhighlight lang=crystal line>
p! 0.class,
0.is_a?(Object),
0.is_a?(Int32),
0.is_a?(Number),
0.is_a?(String)
case 0
when String
puts "String"
when Number
puts "Number"
when Int32
puts "Int32"
when Object
puts "Object"
else
puts "Unknown"
end
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
0.class # => Int32
0.is_a?(Object) # => true
0.is_a?(Int32) # => true
0.is_a?(Number) # => true
0.is_a?(String) # => false
Number
</syntaxhighlight>
暗黙のオブジェクト構文を使うと
:<syntaxhighlight lang=crystal line>
case 0
when .is_a?(String)
puts "String"
when .is_a?(Number)
puts "Number"
when .is_a(Int32)
puts "Int32"
when .is_a(Object)
puts "Object"
else
puts "Unknown"
end
</syntaxhighlight>
:と書くことが出来ます。
:: メソッドは、.is_a? に限定しないので、 .odd? .even? .include? など Bool を返すメソッドなら何でも使えます。
when に対応する式は、1つのことが珍しくないので、その場合は省略可能な then を補うと、1行で書けます。
:<syntaxhighlight lang=crystal line>
case 0
when String then puts "String"
when Number then puts "Number"
when Int32 then puts "Int32"
when Object then puts "Object"
else puts "Unknown"
end
</syntaxhighlight>
 
[TODO:タプルとダミー識別子 _ ]
 
===== 網羅性の検査 =====
when の代わりに in を使用すると、exhaustive case 式が作成されます。exhaustive case では、必要な in 条件を省略するとコンパイル時にエラーとなります。排他的論理和では、when 節と else 節を含むことはできません。
 
コンパイラは、以下の in 条件をサポートしています。
:<syntaxhighlight lang=crystal line>
case 0
when String then puts "String"
when Number then puts "Number"
when Int32 then puts "Int32"
when Object then puts "Object"
else puts "Unknown"
end
</syntaxhighlight>
 
caseの式がユニオンの場合、各要素型を条件として使用することができる。
;組合型チェック:<syntaxhighlight lang=crystal line>
var : ( Bool | Int32 | Float64 )?
var = 3.14
p! (
case var
in Bool then var ? 1 : 0
in Int32 then var
in Float64 then var.to_i
end
)
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
(case var
in Bool
var ? 1 : 0
in Int32
var
in Float64
var.to_i
end) # => 3
</syntaxhighlight>
 
[TODO:case in は enum にも使える]
 
[TODO:短絡評価 && || ]
JavaScriptのswitch文のcase節にも式が使えるので、同じトリックが使えます。 {{See also|JavaScript/制御構造#switch_文の構文}}
 
=== 繰返し ===
652 ⟶ 753行目:
 
===== while =====
while文(while(ホワイル)は条件が'''真'''である間、式を実行しつづけます。
;構文:<syntaxhighlight lang=crystal>
while 条件式