文法の試験範囲 (Gold試験出題数 15/50 約30% )
試験で問われるポイントについて整理していきます。
ブロック
do〜end、{}の違い(結合度のお話)
do〜endと{}では{}の方が結合度が強いという違いがある。
そのため以下の2点について気をつける必要がある。
do〜endを用いる場合は戻り値確認用のpを使ってはいけない。
p (1..10).inject(0) do | sum, i| sum + 1 end #=> TypeError: 0 is not a symbol nor a string # 上記は以下と同じだと解釈され、do〜endは無視されてしまっている p ((1..10).inject(0)) #=> TypeError: 0 is not a symbol nor a string #{}だとinject(0)と{}の結合度が強く、正しく解釈されるため、問題なし p (1..10).inject(0) { | sum, i| sum + 1 } #=> 10
{}の前のメソッド引数は括弧を明示する。
# {}は結合度が強いため、0の引数が{}と解釈されてしまっている 3.downto 0 {|i| puts i} #=> SyntaxError: (irb):1: syntax error, unexpected '{', expecting end-of-input # do〜endならエラーとならないがわかりづらいため、この場合も括弧を明示すべき 3.downto 0 do |i| puts i end #=> 3 #=> 2 #=> 1 #=> 0
do〜end、{}の使い分け(要約)
{}
式の結果を使いたいとき、リソース開放させたいときに使う。
do end
- 上記以外の場合
do〜end、{}の使い分け(詳細)
{}:ブロック付きメソッドがインラインの場合
[1, 2, 3].each {|e| puts e}
{}:ブロック付きメソッドの戻り値を利用する場合
cubic = [1, 2, 3].map {|e| e ** 3}
{}:ブロック付きメソッドからさらにメソッドチェーンする場合
(1..10).select {|e| e.even?}.map {|e| e ** 3}
{}:リソース管理のためにブロックを使う場合
ブロックを抜け出す時にブロック引数のオブジェクトが自動的に解放される。よってcloseが不要
open("foo.txt") {|f| puts f.read }
do end:上記以外の場合
[1, 2, 3].each do |e| puts e end
こちらの内容を転記。私もこのルールで今後、書いていきます。
Rubyのブロック構文の書き分け(do end,{}) - ぬいぐるみライフ(仮)
例外処理
rescueにおける引数省略時のエラー捕捉
StandardErrorを継承したエラーは捕捉される
class MyError1 < StandardError; end begin raise MyError1 rescue => e puts "StandardError!!" end puts "End" #=> StandardError!! #=> End
Exceptionを継承したエラーは捕捉されない
class MyError2 < Exception; end begin raise MyError2 rescue => e puts "Exception!!" end puts "End" #=> End
StandardErrorを継承する例外はアプリケーションエラーの位置付け
Exceptionを継承する例外(StandardErrorは除く。Interrupt 例外など)は捕捉して
継続しないようなエラーが定義されている。よって引数省略時に捕捉するエラーはStandardError。納得した。
例外の階層
- Exception
- fatal
- NoMemoryError
- ScriptError
- NotImplementedError
- LoadError
- SyntaxError
- SecurityError
- SignalException
- Interrupt
- StandardError
- ArgumentError
・
・
- ArgumentError
- SystemExit
- SystemStackError
StandardError以外は即処理が停止するような例外ばかり。
exit
exitはSystemExit例外を発生させる。resucueしないと処理が終了する
begin exit rescue SystemExit puts "SystemExit" end puts "End" SystemExit End
後置rescueの動作
この場合は補足する例外の指定はできない。StanderdErrorしか補足できない
# 通常の例外の書き方 begin @user.name rescue "Unkown" end # 後置の例外の書き方 @user.name rescue "Unkown"
大域脱出
breakではできない、2重ループから一気に抜ける方法。
catch :label do 0.upto(3) do |x| 0.upto(3) do |y| puts "x=#{x}, y=#{y}" throw :label if y == 1 end end end x=0, y=0 x=0, y=1
どんなに深くても「throw ラベル名」でcatch内から一気に脱出できる。
いわゆるgo to文みたいなもの