ようへいの日々精進XP

よかろうもん

2018 年 06 月 21 日 (木)

ジョギング

  • 自宅→香椎神宮香椎浜 で 35 分くらい
  • 引き続き, 右腰, 右臀部の強い張り (ストレッチでなんとかしている)
  • 引き続き, 左足足底筋にも違和感あり

日課

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

今日のるびぃ ~ REx - Ruby Examination にチャレンジ (33) ~

REx - Ruby Examination の問題を自分なりにアレンジした上で 1 〜 3 問くらいずつ解いていく. 正直言ってかなり難しい. 尚, irb に動作確認環境は以下の通り.

$ ruby --version
ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux]
$ irb --version
irb 0.9.6(09/06/30)

クラス変数

以下のコードを実行するどどうなるか.

class S
  @@val = 0
  def initialize
    @@val += 10
  end
end

class C < S
  class << C
    @@val += 10
  end

  def initialize
    @@val += 10
    super
  end
end

C.new
C.new
S.new
S.new

p C.class_variable_get(:@@val)

以下, 解答.

70

以下, irb にて確認.

... 略 ...
irb(main):023:0> 
irb(main):024:0* p C.class_variable_get(:@@val)
70
=> 70

以下のタイミングにて @@val に加算される.

  • クラスメソッドが定義された
  • C.new が呼び出された
  • super により, S クラスの initialize が呼びだされた
  • S.new が呼び出された

ブレイクダウンして irb で確認してみる.

# クラスメソッドを定義した時点で @@val に 10 が代入されている
irb(main):042:0> p C.class_variable_get(:@@val)
10
=> 10
# C.new すると, 10 + 10 = 20, クラスメソッドの 10 を足して 30 になる
irb(main):043:0> C.new
=> #<C:0x0055c197ed57c0>
irb(main):044:0> p C.class_variable_get(:@@val)
30
=> 30
# さらに C.new して, 10 + 10 = 20, 30 + 20 = 50 になる
irb(main):045:0> C.new
=> #<C:0x0055c197ec3de0>
irb(main):046:0> p C.class_variable_get(:@@val)
50
=> 50
# S.new すると 10 となって, 50 + 10 = 60 になる
irb(main):047:0> S.new
=> #<S:0x0055c197eab920>
irb(main):048:0> p C.class_variable_get(:@@val)
60
=> 60
# さらに S.new すると 10 となって, 60 + 10 = 70 になる
irb(main):049:0> S.new
=> #<S:0x0055c197e8a090>
irb(main):050:0> p C.class_variable_get(:@@val)
70
=> 70

クラス変数怖い.

ブロック

以下のコードを実行するとどうなるか.

def foo(*args, &block)
  block.call(*args)
end

foo(1, 2, 3, 4) do |*args|
  p args.length > 0 ? "hello" : args
end

以下, 解答.

hello が出力される

以下, irb による確認.

irb(main):001:0> def foo(*args, &block)
irb(main):002:1>   block.call(*args)
irb(main):003:1> end
=> :foo
irb(main):004:0> 
irb(main):005:0* foo(1, 2, 3, 4) do |*args|
irb(main):006:1*   p args.length > 0 ? "hello" : args
irb(main):007:1> end
"hello"
=> "hello"

以下, 解説より抜粋.

  • 1 行目で引数の値を配列として受け取り, ブロックに配列を渡している
  • 2 行目で * を付けて引数を渡しているので, 配列が展開される (1, 2, 3, 4)
  • 5 行目でブロック変数を渡しているが, *args と宣言されている為, [1, 2, 3, 4] が渡される
  • 6 行目で args.length > 0 の結果は真となり, hello が出力される

フムフム.