LoginSignup
9
10

More than 5 years have passed since last update.

rescue修飾子

Posted at

元ネタにコメントが書けないのでこっちに。

rescue修飾子とは

逆引きRubyの例外の項を見るとわかるけど、中置rescue(=rescue修飾子)は 左辺で例外発生時、右辺を実行するという意味 なので、serialport.read rescue EOFErrorとは、なんか例外が発生したら定数EOFErrorを評価して、その結果EOFErrorクラスを返すという意味になる。なので

rescueで拾ったEOFErrorがreturnされてた

のではなくて、EOFErrorクラスが返されているのであって、発生した例外が返されているわけではない。

serialport.read rescue nilとしたら想定の動作になる。

そもそも

rescue修飾子を忘れてたので、以下のワンライナーでログファイルが一部存在しない場合IOエラーになったので、ググってた。

$ ruby -e 'ARGV.each{|x|puts "***#{x}***";puts IO.read(x)}' pre_process.log process1.log process2.log post_process.log
***pre_process.log***
これから処理するよ…
***process1.log***
一個目処理してるよ…
***process2.log***
-e:1:in `read': No such file or directory @ rb_sysopen - process2.log  (Errno::ENOENT)
        from -e:1:in `block in <main>'
        from -e:1:in `each'
        from -e:1:in `<main>'

単純に直したらこう。

$ ruby -e 'ARGV.each{|x|puts "***#{x}***";puts IO.read(x) rescue puts "not found"}' pre_process.log process1.log process2.log post_process.log
***pre_process.log***
これから処理するよ…
***process1.log***
一個目処理してるよ…
***process2.log***
not found
***post_process.log***
処理終わったよ

しかし2個めのputsが冗長な気がして以下に書き換えると文法エラーになる。イケてもよさそうな気もするけど、カッコの中にはrescue修飾子が書けない様子。

puts(IO.read(x) rescue "not found")

まあ手抜きしないでファイルチェックせーよっていう話だけども。

ARGV.each do |x|
  puts "***#{x}***"
  puts File.exists?(x) ? IO.read(x) : "not found"
end

パーミッション無かったりするとこれでも落ちるけど。
FileTest::readable?のほうが適切か。

しかし

rescue修飾子の評価順は左辺→右辺だけど、(if|unless|while|until)修飾子は 右辺の評価が先 なので、やや迷う気もする。よく次のように書くけど、この場合は右がtrueなら左を実行。

There.do_something if My.foo_enabled?

あとwhile(until)修飾子で、いわゆる後置while(do..while)が実現されているのだが、知らんかったけど、どうも 左辺にbegin - endがある場合は左辺が先、なければ右辺が先 らしい。やや気持ち悪い?
do whileは入力ループなんかで使うと思う。begin x=gets;end while x =~ /on|off/iとか。Rubyのbegin-endは変数スコープを導入しないので、これでも問題なく動く。評価順が変わることでハマるパターンとかないのかな?(例が思いつかないのでなさそう)

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10