ようへいの日々精進XP

よかろうもん

2018 年 06 月 16 日 (土)

ジョギング

  • 自宅→香椎神宮香椎浜 x 1 周で 42 分くらい
  • 臀部の強い張り (ストレッチでなんとかしている)

日課

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

やらかした...

  • ギョームで障害発生...うーん...ごめんなさい
  • ということで, 終日, 調査や検証等...

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

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)

クラスやモジュールの優先順位

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

module Mod1
end

module Mod2
end

class Cls
  include Mod1
  include Mod2
end

p Cls.ancestors

[Cls, Mod2, Mod1, Object, Kernel, BasicObject]

以下, irb による確認.

irb(main):001:0> module Mod1
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module Mod2
irb(main):005:1> end
=> nil
irb(main):006:0> 
irb(main):007:0* class Cls
irb(main):008:1>   include Mod1
irb(main):009:1>   include Mod2
irb(main):010:1> end
=> Cls
irb(main):011:0> 
irb(main):012:0* p Cls.ancestors
[Cls, Mod2, Mod1, Object, Kernel, BasicObject]
=> [Cls, Mod2, Mod1, Object, Kernel, BasicObjec

以下, 解説より抜粋.

  • include はモジュールのメソッドをインスタンスメソッドとして追加する
  • メソッドの探索順は self の後に追加される
  • 複数回 include された場合には, 後から宣言されたモジュールのメソッドが優先される (設問では Mod2 のメソッドが優先される)

Module#ancestors について, ドキュメントより抜粋.

クラス、モジュールのスーパークラスとインクルードしているモジュールを優先順位順に配列に格納して返します。

以下, irb による実行例.

irb(main):001:0> module Foo
irb(main):002:1> end
=> nil
irb(main):003:0> class Bar
irb(main):004:1>   include Foo
irb(main):005:1> end
=> Bar
irb(main):006:0> class Baz < Bar
irb(main):007:1>   p ancestors        # スーパークラスとインクルードしているモジュールの優先順位を返す
irb(main):008:1>   p included_modules # インクルードしているモジュールを返す
irb(main):009:1>   p superclass       # スーパークラスを返す
irb(main):010:1> end
[Baz, Bar, Foo, Object, Kernel, BasicObject]
[Foo, Kernel]
Bar
=> Bar

ブロック引数の渡し方

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

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

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

例外が発生する

以下, irb にて確認.

irb(main):001:0> def foo(&block, *args)
irb(main):002:1>   block.call(*args)
irb(main):003:1> end
SyntaxError: (irb):1: syntax error, unexpected ',', expecting ')'
def foo(&block, *args)
               ^
(irb):3: syntax error, unexpected keyword_end, expecting end-of-input

以下, 解説より抜粋.

  • ブロック引数は仮引数の中で最後に記述する
  • ブロック引数はメソッド定義につき 1 つしか指定出来ない
  • 他の引数がある場合には, ブロック引数は必ず最後に指定する必要がある

以下, 正しく動作するコード.

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

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

以下, 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 ? "AAA" : args
irb(main):007:1> end
"AAA"
=> "AAA"

フムフム.