ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
リゾート温泉ホテルごっこ
奥さんの体調がイマイチだったので, 自宅をリゾート温泉ホテルに見立てて, お風呂にバスクリンのお湯を張って半身浴をさせたり, 小洒落た朝ごはんを作って食べさせたりした. 今は焦らず, ゆっくりのんびり元気になって欲しい.
頭痛
- 夜になって肩がとても張って, 右側の頭痛が激しい
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (24) ~
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)
Enumerator
以下のコードの実行結果と同じ結果となるような実装を選択しから選ぶ.
# コード class Array def succ_each(step = 1) return enum_for(:succ_each, step) unless block_given? each do |int| yield int + step end end end p [98, 99, 100].succ_each(2).map {|succ_chr| succ_chr.chr} [101, 102, 103].succ_each(5) do |succ_chr| p succ_chr.chr end # 実行結果 ["d", "e", "f"] "j" "k" "l"
まずは, コードを irb で動作確認.
... irb(main):011:0* p [98, 99, 100].succ_each(2).map {|succ_chr| succ_chr.chr} ["d", "e", "f"] => ["d", "e", "f"] irb(main):012:0> irb(main):013:0* [101, 102, 103].succ_each(5) do |succ_chr| irb(main):014:1* p succ_chr.chr irb(main):015:1> end "j" "k" "l" => [101, 102, 103]
以下, 解答.
# 解答 1 class Array def succ_each(step = 1) return to_enum(:succ_each, step) unless block_given? each do |int| yield int + step end end end p [98, 99, 100].succ_each(2).map {|succ_chr| succ_chr.chr} [101, 102, 103].succ_each(5) do |succ_chr| p succ_chr.chr end # 解答 2 class Array def succ_each(step = 1) unless block_given? Enumerator.new do |yielder| each do |int| yielder << int + step end end else each do |int| yield int + step end end end end p [98, 99, 100].succ_each(2).map {|succ_chr| succ_chr.chr} [101, 102, 103].succ_each(5) do |succ_chr| p succ_chr.chr end
以下, 解説より抜粋.
- ブロックを渡す場合と, チェーンを行う場合の両方を考慮する必要がある
- チェーンを行う場合は
Enumerator
オブジェクトを作成する必要がある Enumerator
オブジェクトの作成に必要なメソッドはenum_for
とto_enum
がある- 設問のコードでは
enum_for
を使っているので, 選択肢のうちto_enum
を使っている選択肢が答えの一つになる - 尚,
to_enum
は引数にメソッド名とそのメソッドに必要な引数を指定する必要がある為, 設問のコードでは,succ_each
メソッドに引数2
を渡している為,Enumerator
オブジェクトを作成するときに必要になる Enumerator
オブジェクトはnew
メソッドで作成することが出来る為, 以下のように実装することも出来る
class Array def succ_each(step = 1) unless block_given? # ブロックが無い場合は、オブジェクトを作成 Enumerator.new do |yielder| each do |int| yielder << int + step end end else # ブロックがある場合の実装 each do |int| yield int + step end end end end
- チェーンした先で渡されたブロックを評価するためには
Enumerator::Yielder
のオブジェクトを利用する - オブジェクトに対して,
<<
を実行することでブロック内で評価した結果を受け取ることが出来る
フムフム.