ようへいの日々精進XP

よかろうもん

2018 年 04 月 17 日(火)

ジョギング

  • 香椎浜 x 2 周
  • 黄砂が酷い感じがしたのでマスクで走った

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

テンション

  • 最近, ギョームにおいてテンション下がり気味

川内優輝選手

すごいぞ!

www.nikkansports.com

exercism.io

exercism.io が面白い. Ruby で 2 問目を解いたあたりから, 世界の壁を感じている.

だが, 他の人の書き方等を読んでいるととても勉強になる.

今日のるびぃ ~ Ruby 技術者認定試験 Gold 演習問題を解いていく (27) ~

もう何度か解いているけど, Ruby 技術者認定試験合格教本 の演習問題と模擬試験を数問ずつ解いていく. ポイントは, 問題が何について問われているかがちゃんと理解出来ていること.

Q49. 組み込みライブラリ

Kernel モジュールの load と require について, 適切な記述を選べ.

  1. require は同じファイルを複数回ロードすることを防ごうとする

他の選択肢.

  1. load はバイナリエクステンションはロード出来る => 出来ない
  2. load は拡張子無しのライブラリ名を渡す => 拡張子を付ける
  3. require はバイナリエクステンションはロード出来ない=> ロード出来る

以下, 解説より抜粋.

複数回ロード バイナリエクステンション 拡張子補完
load する ロード出来ない しない
require しない ロード出来る する

以下, load だとロードした分だけ, グローバル変数 $var に追記される様子.

$ cat file1.rb 
# file1.rb
$var += 1
$ irb
irb(main):001:0> $var = 0
=> 0
irb(main):003:0> load 'file1.rb'
=> true
irb(main):004:0> load 'file1.rb'
=> true
irb(main):005:0> load 'file1.rb'
=> true
irb(main):006:0> p $var
3
=> 3

Q50. 組み込みライブラリ

以下のコードを実行するとどうなるか, 全て選べ.

t1 = Thread.start do
  raise ThreadError
end
sleep
  1. 例外が発生するが, メッセージを出力せずに停止の状態になる
  2. -d オプションを付けた場合には, 例外のメッセージを出力して終了する

以下, 実行例.

$ ruby thread.rb

(何も出力されない)

^Cthread.rb:4:in `sleep': Interrupt
        from thread.rb:4:in `<main>'

# デバッグモードでの実行
$ ruby -d thread.rb 
Exception `LoadError' at /path/to/.rbenv/versions/2.1.10/lib/ruby/2.1.0/rubygems.rb:1194 - cannot load such file -- rubygems/defaults/operating_system
Exception `LoadError' at /path/to/.rbenv/versions/2.1.10/lib/ruby/2.1.0/rubygems.rb:1203 - cannot load such file -- rubygems/defaults/ruby
thread.rb:1: warning: assigned but unused variable - t1
Exception `ThreadError' at thread.rb:2 - ThreadError
Exception `ThreadError' at thread.rb:4 - ThreadError
thread.rb:2:in `block in <main>': ThreadError (ThreadError)

以下, 解説より抜粋.

  • マルチスレッドで例外が発生し, raise で処理されない場合, 例外が発生したスレッドだけが警告無しで終了し, 他のスレッドは実行を続ける
  • -d オプションを付与するとデバッグモードでの実行となり, いずれかのスレッドで例外が発生した時点でインタプリタ全体が中断する

ドキュメントより「例外発生時のスレッドの振る舞い」について引用.

あるスレッドで例外が発生し、そのスレッド内で rescue で捕捉されなかっ た場合、通常はそのスレッドだけがなにも警告なしに終了されます。ただ しその例外で終了するスレッドを Thread#join で待っている他の スレッドがある場合、その待っているスレッドに対して、同じ例外が再度 発生します。

インタプリタ全体を中断させる方法は以下の三つ.

  • デバッグモードで Ruby インタプリタを起動した場合 (環境変数 $DEBUG=true 又は -d オプションを付けて Ruby を起動した場合)
  • Thread.abort_on_exception でフラグを設定した場合
  • Thread#abort_on_exception で指定 したスレッドのフラグを設定した場合

以下, こちら の記事に掲載されていた記事を参考にさせて頂いてスレッドを体験した.

t1 = Thread.start {
  6.times do
    puts "スレッド1を実行しています"
    sleep(0.5)
  end
}

3.times do
  puts "メインスレッドを実行します"
end

puts "スレッド1の終了を待っています"
t1.join
puts "スレッド1が終わったので、メインスレッドを終了します"

実行すると, 以下のように出力される.

$ ruby thread.rb 
メインスレッドを実行します
メインスレッドを実行します
メインスレッドを実行します
スレッド1の終了を待っています
スレッド1を実行しています
スレッド1を実行しています
スレッド1を実行しています
スレッド1を実行しています
スレッド1を実行しています
スレッド1を実行しています
スレッド1が終わったので、メインスレッドを終了します

join を利用することで, メインスレッドは他のスレッド (上記の例だと「スレッド 1」) の終了を待つことが出来るようになる.

フムフム.