ようへいの日々精進XP

よかろうもん

2018 年 06 月 18 日 (月)

ジョギング

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

日課

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

関西地方で大きな地震

  • 大きな被害が出ていた
  • 親戚や友人の皆さんは特にケガもなくということで一安心
  • これから天気も悪くなるとのことなので, 引き続き気をつけてくださいmm

2019/06/18 今日のるびぃ

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

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 Foo
  NAME = "foo"

  def self.name
    const_get(:NAME)
  end
end

class Bar < Foo
  NAME = "bar"
end

puts Bar.name

bar が表示される

以下, irb にて確認.

irb(main):001:0> class Foo
irb(main):002:1>   NAME = "foo"
irb(main):003:1> 
irb(main):004:1*   def self.name
irb(main):005:2>     const_get(:NAME)
irb(main):006:2>   end
irb(main):007:1> end
=> :name
irb(main):008:0> 
irb(main):009:0* class Bar < Foo
irb(main):010:1>   NAME = "bar"
irb(main):011:1> end
=> "bar"
irb(main):012:0> 
irb(main):013:0* puts Bar.name
bar
=> nil

以下, 解説より抜粋.

  • Class#name はクラス名を文字列で返す
  • Foo#name クラスは Class#name をオーバーライドしているので, const_get が呼ばれることになる
  • const_get は, self に定義された定数を探索し, 自クラスに定義がない場合は, メソッドと同様に探索を行う

ドキュメントを見てみると, Class#name というメソッドが無いんだが...きっと, Module#name のことなんだろうなあということで, Module#name 前提でちょっと掘り下げる.

irb(main):001:0> class Foo; end
=> nil
irb(main):002:0> Foo.name
=> "Foo"
irb(main):003:0> Foo.inspect
=> "Foo"
irb(main):004:0> Foo.to_s
=> "Foo"

Module#nameModule#inspecModule#to_s と同義である. このメソッドが返す「クラス/モジュール名」とは, 正確には「クラスパス」を指す.

irb(main):005:0> class Foo
irb(main):006:1>   class Bar
irb(main):007:2>   end
irb(main):008:1>   Bar.name
irb(main):009:1> end
=> "Foo::Bar"
irb(main):010:0> Foo.name
=> "Foo"
irb(main):012:0> Foo::Bar.name
=> "Foo::Bar"
irb(main):013:0> class Foo
irb(main):014:1>   class Baz; end
irb(main):015:1> end
=> nil
irb(main):016:0> Foo::Baz.name
=> "Foo::Baz"

引き続き, const_get について.

irb(main):001:0> module Bar
irb(main):002:1>   BAR = 1
irb(main):003:1> end
=> 1
irb(main):004:0> class Object
irb(main):005:1>   include Bar
irb(main):006:1> end
=> Object
# Object では include されたモジュールの定義を探索する
irb(main):007:0> Object.const_get(:BAR)
=> 1
# 存在しない定数にアクセスしようとすると例外 (NameError) が発生する
irb(main):008:0> Object.const_get(:FOO)
NameError: uninitialized constant FOO
... 略 ...
# トップレベルに定数を定義して, その定数を参照する場合
irb(main):009:0> BAR = 10
=> 10
irb(main):011:0> Object.const_get(:BAR)
=> 10
# 完全修飾名で定数を指定した場合には, モジュールに定義されている定数を参照する
irb(main):013:0> Object.const_get('Bar::BAR')
=> 1
irb(main):007:0> class Baz
irb(main):008:1>   include Bar
irb(main):009:1> end
=> Baz
irb(main):010:0> Baz.const_get(:BAR)
=> 1
# 第二引数に false を付けると, 自身に定義された定数から探す
irb(main):011:0> Baz.const_get(:BAR, false)
NameError: uninitialized constant Baz::BAR
... 略 ...
irb(main):012:0> class Baz
irb(main):013:1>   BAR = 2
irb(main):014:1> end
=> 2
irb(main):015:0> Baz.const_get(:BAR)
=> 2
irb(main):016:0> Baz.const_get(:BAR, false)
=> 2
irb(main):017:0> Baz.const_get('Bar:BAR')
NameError: wrong constant name Bar:BAR
... 略 ...
irb(main):018:0> Baz.const_get('Bar::BAR')
=> 1

const_get は, 引数 (String か Symbol で指定) で指定された定数を取り出す. 存在していない定数を参照すると NameError の例外が発生する. 第二引数に false を指定すると, 自身に定義された定数から探す.

フムフム.

2018 年 06 月 17 日 (日)

ジョギング

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

日課

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

引き続き

  • 仕事をしつつ, 昨日よりは少しのんびり過ごすことが出来た
  • どこにも連れて行ってあげられなかったので, 奥さんには申し訳ないと思っている

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

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)

method_missing

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

module Mod
  def method_missing(id, *args)
    puts "Mod#method_missing"
  end
end
class Cls1
  include Mod
  def method_missing(id, *args)
    puts "Cls1#method_missing"
  end
end
class Cls2 < Cls1
  class << self
    def method_missing(id, *args)
      puts "Cls2.method_missing"
    end
  end
end

Cls2.new.dummy_method

Cls1#method_missing

以下, irb にて確認.

irb(main):001:0> module Mod
irb(main):002:1>   def method_missing(id, *args)
irb(main):003:2>     puts "Mod#method_missing"
irb(main):004:2>   end
irb(main):005:1> end
=> :method_missing
irb(main):006:0> class Cls1
irb(main):007:1>   include Mod
irb(main):008:1>   def method_missing(id, *args)
irb(main):009:2>     puts "Cls1#method_missing"
irb(main):010:2>   end
irb(main):011:1> end
=> :method_missing
irb(main):012:0> class Cls2 < Cls1
irb(main):013:1>   class << self
irb(main):014:2>     def method_missing(id, *args)
irb(main):015:3>       puts "Cls2.method_missing"
irb(main):016:3>     end
irb(main):017:2>   end
irb(main):018:1> end
=> :method_missing
irb(main):019:0> 
irb(main):020:0* Cls2.new.dummy_method
Cls1#method_missing
=> nil

以下, 解説より抜粋.

  • method_missing は, 継承チェーンを辿った末にメソッドが見つからなかった時に呼び出される
  • method_missing も継承チェーンを辿る
  • class << self; end で定義されたメソッドは, 特異クラスのインスタンスメソッドになる為, 設問コードでは呼び出すことが出来ない

以下のように呼び出すことで, Cls2 特異メソッドの method_missing を呼び出すことが出来る.

irb(main):021:0> Cls2.dummy_method
Cls2.method_missing
=> nil

メソッドの可視性

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

class Cls
private
  def initialize
  end
end

p Cls.new.public_methods.include? :initialize

false が出力される.

以下, irb にて確認.

irb(main):001:0> class Cls
irb(main):002:1> private
irb(main):003:1>   def initialize
irb(main):004:2>   end
irb(main):005:1> end
=> :initialize
irb(main):006:0> 
irb(main):007:0* p Cls.new.public_methods.include? :initialize
false
=> false

以下, 解説より抜粋.

  • initialize の可視性はprivateに設定されている
  • initialize の可視性を public に設定したとしても, 必ず private となる

Object#private_methods というメソッドも用意されている.

irb(main):001:0> class Cls
irb(main):002:1>   def initialize
irb(main):003:2>   end
irb(main):004:1> end
=> :initialize
irb(main):005:0> Cls.new.private_methods(false)
=> [:initialize]
irb(main):006:0> Cls.new.private_methods(false).include?(:initialize)
=> true

Object#private_methods の引数に false を渡すと, スーパークラスに定義されているメソッドを除いて出力される.

フムフム.

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"

フムフム.

2018 年 06 月 15 日 (金)

ジョギング

  • 自宅→香椎神宮香椎浜
  • 引き続き, 右足 (右腰から右足全体) にかけて痛み... は, 多少, 今日は良かった

日課

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

香椎ミートアップ

  • ということで, 香椎駅の中に出来た竹の家に行ってきた
  • 色々ワイワイ喋って楽しかったけど呑み過ぎた感

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

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)

Ruby コマンドラインオプション

Ruby で使用可能なオプションではないものを選択する.

  • -t
  • -l
  • -p
  • -f

以下, 利用可能ではないオプション.

  • -t
  • -f

以下, 利用可能なオプション (解説より抜粋)

  • -l
    • 各行の最後に String#chop! を実行する (ドキュメントより引用: 行末の自動処理を行います。まず、$\ を $/ と同じ値に設定し, printでの出力 時に改行を付加するようにします。)
  • -p
    • -n オプションと同様に $_ を出力する
    • $_ とは, 最後に Kernel.#gets または Kernel.#readline で読み込んだ文字列です。 (ドキュメントより引用)

以下, 実行例.

# 通常は print を利用する場合, 改行は付加されない
$ ruby -e 'print "01234567890"'
01234567890$
# -l オプションを付けると, print を利用した際に改行を付加する
$ ruby -l -e 'print "01234567890"'
01234567890
# -p オプションのサンプル
$ echo foo | ruby -p -e '$_.tr! "a-z", "A-Z"'
FOO
# ちなみに, -n オプションは以下のような挙動となる
$ echo 'foo' | ruby -n -e 'print'
foo

Enumerator::Lazy

以下のコードは Enumerator::Lazy を利用している. 先頭から 5 つの値を取り出す為にはどのメソッドが必要か.

(1..100).each.lazy.chunk(&:even?)

以下, 解答.

take(5).force first(5)

以下, irb による実行例.

irb(main):001:0> (1..100).each.lazy.chunk(&:even?)
=> #<Enumerator::Lazy: #<Enumerator: #<Enumerator::Generator:0x0055758c2a6dc0>:each>>
irb(main):002:0> (1..100).each.lazy.chunk(&:even?).first(5)
=> [[false, [1]], [true, [2]], [false, [3]], [true, [4]], [false, [5]]]
irb(main):003:0> (1..100).each.lazy.chunk(&:even?).take(5)
=> #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator: #<Enumerator::Generator:0x0055758c24f048>:each>>:take(5)>
irb(main):004:0> (1..100).each.lazy.chunk(&:even?).take(5).force
=> [[false, [1]], [true, [2]], [false, [3]], [true, [4]], [false, [5]]]
irb(main):006:0> (1..100).each.lazy.chunk(&:even?).force.take(5)
=> [[false, [1]], [true, [2]], [false, [3]], [true, [4]], [false, [5]]]
irb(main):007:0> (1..100).each.lazy.chunk(&:even?).first
=> [false, [1]]
irb(main):008:0> (1..100).each.lazy.chunk(&:even?).force.first(5)
=> [[false, [1]], [true, [2]], [false, [3]], [true, [4]], [false, [5]]]

以下, 解説より抜粋.

  • 単純に値を取り出すには, Enumerator::Lazy#force 又は Enumerator::Lazy#first を利用する
  • 設問では, 「先頭から 5 つの値」とあるので, first(5) を利用する
  • Enumerator::Lazy#force は全ての値を取り出す (全ての要素を含む配列を返す) が, 5 つの値を取り出す為には Enumerator::Lazy#take 又は Enumerator::Lazy#first を利用する
  • Enumerator::Lazy#takeEnumerable#take と異なり, Enumerator::Lazyインスタンスを戻り値となる為, Enumerator::Lazy#force で実際の値を取り出す

フムフム.

2018 年 06 月 14 日 (木)

ジョギング

  • 自宅→香椎神宮香椎浜
  • 引き続き, 右足 (右腰から右足全体) にかけて痛み... は, 多少, 今日は良かった

日課

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

夕飯

  • AJINOMOTO の冷凍餃子, タコ刺し (絶品), 枝豆

ひとやま

  • 奥さん, ギョームにてひとやま越えたらしい
  • おつかれさま

体調

  • 終日イマイチ...
  • ホントに加齢を感じる今日このごろ

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

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)

Mix-in

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

module M
  def class_m
    "class_m"
  end
end

class C
  include M
end

p C.methods.include? :class_m

false

以下, irb にて確認.

irb(main):001:0> module M
irb(main):002:1>   def class_m
irb(main):003:2>     "class_m"
irb(main):004:2>   end
irb(main):005:1> end
=> :class_m
irb(main):006:0> 
irb(main):007:0* class C
irb(main):008:1>   include M
irb(main):009:1> end
=> C
irb(main):010:0> 
irb(main):011:0* p C.methods.include? :class_m
false
=> false

以下, 解説より抜粋.

  • include は Module のインスタンスメソッドを Mix-in するメソッド
  • C.methods は C の特異メソッドを表示する

従って, C#class_mインスタンスメソッドとなり, C.methods では表示されないが, 以下のようにインスタンス化することで, true インスタンスメソッドとなり true となる.

irb(main):012:0> p C.new.methods.include? :class_m
true
=> true

インスタンスメソッド, 特異メソッド

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

class Cls
  class << Cls
    def foo
      'foo'
    end
  end

  def foo
    'FOO'
  end
end

p Cls.new.foo

FOO

以下, irb による確認.

irb(main):001:0> class Cls
irb(main):002:1>   class << Cls
irb(main):003:2>     def foo
irb(main):004:3>       'foo'
irb(main):005:3>     end
irb(main):006:2>   end
irb(main):007:1> 
irb(main):008:1*   def foo
irb(main):009:2>     'FOO'
irb(main):010:2>   end
irb(main):011:1> end
=> :foo
irb(main):012:0> 
irb(main):013:0* p Cls.new.foo
"FOO"
=> "FOO"

以下, 解説より抜粋.

  • 特異クラス内 class << Cls; end に宣言されたメソッドは特異メソッドとなる
  • 特異メソッドは def Cls.foo: end でも宣言することも出来る
  • 設問コードでは, インスタンスを作成しそのメソッドを呼び出している為, インスタンスメソッドの FOO を返すメソッドが呼ばれる

以下のように書くと foo が出力される.

irb(main):014:0> p Cls.foo
"foo"
=> "foo"

フムフム.

2018 年 06 月 13 日 (水)

ジョギング

  • 自宅→香椎神宮香椎浜
  • 引き続き, 右足 (右腰から右足全体) にかけて痛み... 日に日にひどくなる感じ...
  • ストレッチでごまかす

日課

  • 休み

fukuoka.rb

fukuokarb.connpass.com

に参加した.

以下の 2 つのプルリクエストをこさえた.

github.com

github.com

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

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_eval による定数参照

以下のコードは Hello, world を表示する. 同じ結果となるコードを複数選択する.

module M
  CONST = "Hello, world"

  class C
    def awesome_method
      CONST
    end
  end
end

p M::C.new.awesome_method

以下, 解答.

# 解答(1)
class C
end

module M
  CONST = "Hello, world"

  C.class_eval do
    def awesome_method
      CONST
    end
  end
end

p C.new.awesome_method

# 解答 (2)
class C
  CONST = "Hello, world"
end

module M
  C.class_eval(<<-CODE)
    def awesome_method
      CONST
    end
  CODE
end

p C.new.awesome_method

以下, irb にて確認.

# 設問コード
irb(main):001:0> module M
irb(main):002:1>   CONST = "Hello, world"
irb(main):003:1> 
irb(main):004:1*   class C
irb(main):005:2>     def awesome_method
irb(main):006:3>       CONST
irb(main):007:3>     end
irb(main):008:2>   end
irb(main):009:1> end
=> :awesome_method
irb(main):010:0> 
irb(main):011:0* p M::C.new.awesome_method
"Hello, world"
=> "Hello, world"

# 解答(1)
irb(main):001:0> class C
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module M
irb(main):005:1>   CONST = "Hello, world"
irb(main):006:1> 
irb(main):007:1*   C.class_eval do
irb(main):008:2*     def awesome_method
irb(main):009:3>       CONST
irb(main):010:3>     end
irb(main):011:2>   end
irb(main):012:1> end
=> :awesome_method
irb(main):013:0> 
irb(main):014:0* p C.new.awesome_method
"Hello, world"
=> "Hello, world"


# 解答(2)
irb(main):001:0> class C
irb(main):002:1>   CONST = "Hello, world"
irb(main):003:1> end
=> "Hello, world"
irb(main):004:0> 
irb(main):005:0* module M
irb(main):006:1>   C.class_eval(<<-CODE)
irb(main):007:2"     def awesome_method
irb(main):008:2"       CONST
irb(main):009:2"     end
irb(main):010:2"   CODE
irb(main):011:1> end
=> :awesome_method
irb(main):012:0> 
irb(main):013:0* p C.new.awesome_method
"Hello, world"
=> "Hello, world"

以下, 解説より抜粋.

  • 解答 (1)
    • class_eval にブロックを渡した場合は, ブロック内のネストはモジュール M になる
    • そのコンテキストから定数を探索するので "Hello, world" が表示される
  • 解答 (2)
    • class_eval に文字列を渡した場合のネストの状態はクラス C となる
    • CONST はクラス C にある為, "Hello, world" が表示される

念の為, ブロックで渡した場合と, 文字列で渡した場合のネストの状態を確認してみる.

# class_eval のブロック渡し
irb(main):001:0> class C
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module M
irb(main):005:1>   C.class_eval do
irb(main):006:2*     Module.nesting
irb(main):007:2>   end
irb(main):008:1> end
=> [M]
irb(main):009:0> exit

# class_eval の文字列渡し
irb(main):001:0> class C
irb(main):002:1> end
=> nil
irb(main):003:0> 
irb(main):004:0* module M
irb(main):005:1>   C.class_eval(<<-CODE)
irb(main):006:2"     Module.nesting
irb(main):007:2"   CODE
irb(main):008:1> end
=> [C, M]

上記のように, ネストの状態が異なる為, 定数を探索するコンテキストも異なることが解る.

フムフム.

2018 年 06 月 12 日 (火)

ジョギング

  • 自宅→香椎神宮香椎浜
  • 引き続き, 右足 (右腰から右足全体) にかけて痛み... 日に日にひどくなる感じ

日課

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

奥さん

  • 少し元気になったようで良かった

明日は

fukuokarb.connpass.com

に参加する予定.

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

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 C
  CONST = "AAA"
end

module M
  CONST = "BBB"
end

module M
  class C
    CONST = "CCC"
  end
end

module M
  class C
    p CONST
  end
end

CCC と表示される

以下, irb にて確認.

irb(main):001:0> class C
irb(main):002:1>   CONST = "AAA"
irb(main):003:1> end
=> "AAA"
irb(main):004:0> 
irb(main):005:0* module M
irb(main):006:1>   CONST = "BBB"
irb(main):007:1> end
=> "BBB"
irb(main):008:0> 
irb(main):009:0* module M
irb(main):010:1>   class C
irb(main):011:2>     CONST = "CCC"
irb(main):012:2>   end
irb(main):013:1> end
=> "CCC"
irb(main):014:0> 
irb(main):015:0* module M
irb(main):016:1>   class C
irb(main):017:2>     p CONST
irb(main):018:2>   end
irb(main):019:1> end
"CCC"
=> "CCC"

以下, 解説より抜粋.

  • 設問では, ネストされた class C の定数 CONST を参照している
  • トップレベルの class C とネストされた class C では, 定数 CONST の内容は異なる

尚, トップレベル class C の定数を参照したい場合には, 以下のような方法で参照する.

irb(main):020:0> module M
irb(main):021:1>   class ::C
irb(main):022:2>     p CONST
irb(main):023:2>   end
irb(main):024:1> end
"AAA"
=> "AAA"
irb(main):025:0> class Object
irb(main):026:1>   class C
irb(main):027:2>     p CONST
irb(main):028:2>   end
irb(main):029:1> end
"AAA"
=> "AAA"

クラス, モジュールのネスト状態を確認する場合, Module.nesting を利用する.

irb(main):001:0> class C
irb(main):002:1>   p Module.nesting
irb(main):003:1> end
[C]
=> [C]
irb(main):004:0> 
irb(main):005:0* module M
irb(main):006:1>   class C
irb(main):007:2>     p Module.nesting
irb(main):008:2>   end
irb(main):009:1> end
[M::C, M]
=> [M::C, M]

上記のように, クラスやネストの状態が出力される.

フムフム.

2018 年 06 月 11 日 (月)

ジョギング

  • 雨の為, お休み

日課

  • お休み

引き続き...体調が...

  • 肩がとても張って, 右側の頭痛が激しい

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

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)

lazy と take

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

p (1..10).lazy.map{|num|
  num * 2
}.take(3).inject(0, &:+)

12 と表示される

以下, irb による動作確認.

irb(main):001:0> p (1..10).lazy.map{|num|
irb(main):002:1*   num * 2
irb(main):003:1> }.take(3).inject(0, &:+)
12
=> 12

以下, 解説より抜粋.

  • lazyEnumerator::Lazy クラスを返す
  • Enumerator::Lazy クラスは mapselect メソッドに遅延評価を提供する
  • take(3) が実行されると 1 から 3 まで map に渡されたものと判断され, inject に渡される

設問のコードから lazy を除いて実行してみる.

# lazy メソッド無し, map された結果が返る
irb(main):001:0> e = (1..10).map{|num|
irb(main):002:1*   num * 2
irb(main):003:1> }
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# take メソッドで Array クラスの変数 e から最初の 3 要素を取得する
irb(main):004:0> t = e.take(3)
=> [2, 4, 6]
# inject メソッドを利用して 3 要素の合計を計算している 
irb(main):005:0> t.inject(0, &:+)
=> 12

Enumerable#map (Enumerable#collect) メソッドについて. (ドキュメントより引用)

  • 各要素に対してブロックを評価した結果を全て含む配列を返す
  • ブロックを省略した場合, 上で説明した繰り返しを実行し, その結果として得られる配列を返すような Enumerator オブジェクトを返す
  • Enumerable#collect も同様の機能を提供する
irb(main):004:0> p [1, 2, 3].map {|n| n * 3 }
[3, 6, 9]
=> [3, 6, 9]
irb(main):006:0> a = [1, 2, 3].map
=> #<Enumerator: [1, 2, 3]:map>

Enumerable#select (Enumerable#find_all) メソッドについて. (ドキュメントより引用)

  • 各要素に対してブロックを評価した値が真であった要素を全て含む配列を返す
  • 真になる要素がひとつもなかった場合は空の配列を返す
  • ブロックを省略した場合, 各要素に対しブロックを評価して真になった値の配列を返すような Enumerator を返す
  • Enumerable#find_all も同様の機能を提供する
irb(main):001:0> (1..10).find_all
=> #<Enumerator: 1..10:find_all>
irb(main):002:0> (1..10).find_all { |i| i % 3 == 0 }
=> [3, 6, 9]
irb(main):003:0> [1,2,3,4,5].select
=> #<Enumerator: [1, 2, 3, 4, 5]:select>
irb(main):004:0> [1,2,3,4,5].select { |num| num.even? } 
=> [2, 4]

Enumerable#inject メソッドについて. (ドキュメントより引用)

  • リストのたたみこみ演算を行う
  • 最初に初期値 init と self の最初の要素を引数にブロックを実行する
  • 2 回目以降のループでは、前のブロックの実行結果と self の次の要素を引数に順次ブロックを実行する
  • 最後の要素まで繰り返して最後のブロックの実行結果を返す
  • 要素が存在しない場合は init を返す
  • 初期値 init を省略した場合はには, 最初に先頭の要素と 2 番目の要素をブロックに渡す
  • 要素が 1 つしかなければブロックを実行せずに最初の要素を返し, 要素がなければブロックを実行せずに nil を返す
# 合計の計算
irb(main):005:0> p [2, 3, 4, 5].inject {|result, item| result + item }
14
=> 14
# 自乗和を計算する. 初期値 (0) をセットする必要がある.
irb(main):006:0> p [2, 3, 4, 5].inject(0) {|result, item| result + item**2 }
54
=> 54

以下のように書いても同様の結果を得ることが出来る.

irb(main):007:0> result = 0
=> 0
irb(main):008:0> [1, 2, 3, 4, 5].each {|v| result += v }
=> [1, 2, 3, 4, 5]
irb(main):009:0> p result
15
=> 15
irb(main):010:0> p [1, 2, 3, 4, 5].inject(:+)
15
=> 15
irb(main):001:0> p ["b", "c", "d"].inject("abbccddde", :squeeze)
"abcde"
=> "abcde"

inject メソッドの応用

(0..10).inject([1, 1]) {|fib, i| fib << fib[i] + fib[i+1] }

以下, irb にて確認.

irb(main):001:0> (0..10).inject([1, 1]) {|fib, i| fib << fib[i] + fib[i+1] }
=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
  • inject を使って Ruby の Array や Enumerable の各種メソッドを再実装する
# Array クラスを継承する List クラスを作成, 同時に Array クラスのメソッド達を undef して利用出来なくしている
irb(main):001:0> class List < Array
irb(main):002:1>   undef_method *%w(inject map size at index select reject detect all? any? one? none? min max minmax take_while grep include? partition group_by count join assoc zip reverse values_at compact take flat_map product)
irb(main):003:1> end
=> List
# まずは inject メソッドを再実装
irb(main):005:0> class List < Array
irb(main):006:1>   def inject(m, &blk)
irb(main):007:2>     return m if empty?
irb(main):008:2>     (drop 1).inject( yield(m, first), &blk)
irb(main):009:2>   end
irb(main):010:1> end
=> :inject
irb(main):011:0> List[1,2,3,4,5].inject(0) { |m, x| m + x }
=> 15
# 続いて, map メソッドを再実装
irb(main):012:0> class List < Array
irb(main):013:1>   def map
irb(main):014:2>     inject([]) { |m, x| m << yield(x) }
irb(main):015:2>   end
irb(main):016:1> end
=> :map
irb(main):017:0> List[1,2,3,4,5].map { |x| x**2 }
=> [1, 4, 9, 16, 25]

こちらの記事を引用させて頂いた. とても面白かった.

フムフム.

2018 年 06 月 10 日 (日)

ジョギング

  • 自宅→香椎神宮香椎浜 x 1 周
  • 引き続き, 右足 (右腰から右足全体) にかけて痛み

日課

  • (腕立て 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_forto_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 のオブジェクトを利用する
  • オブジェクトに対して, << を実行することでブロック内で評価した結果を受け取ることが出来る

フムフム.

2018 年 06 月 09 日 (土)

ジョギング

日課

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

晴れ間

  • 梅雨の晴れ間
  • 洗濯頑張った

マッサージ

  • なんだか体調も悪いし, 足も痛かったのでマッサージをしてもらった
  • だいぶんほぐれた気がするけど...

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

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)

モジュール, クラスのネスト

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

# コード 1
class Cls1
  p Module.nesting
end

# コード 2
module Mod
  class ::Cls1
    p Module.nesting
  end
end

# コード 3
module Mod
  class Cls1
    p Module.nesting
  end
end

コード 1 は [Cls1] と表示される コード 2 は [Cls1, Mod] と表示される コード 3 は [Mod::Cls1, Mod] と表示される

以下, irb にて確認.

irb(main):001:0> class Cls1
irb(main):002:1>   p Module.nesting
irb(main):003:1> end
[Cls1]
=> [Cls1]
irb(main):004:0> 
irb(main):005:0* module Mod
irb(main):006:1>   class ::Cls1
irb(main):007:2>     p Module.nesting
irb(main):008:2>   end
irb(main):009:1> end
[Cls1, Mod]
=> [Cls1, Mod]
irb(main):010:0> 
irb(main):011:0* module Mod
irb(main):012:1>   class Cls1
irb(main):013:2>     p Module.nesting
irb(main):014:2>   end
irb(main):015:1> end
[Mod::Cls1, Mod]
=> [Mod::Cls1, Mod]

以下, 解説より抜粋.

  • 先頭に :: がある場合はモジュール内にあっても, トップレベルのクラス Cls1 と同義である
  • Mod::Cls1 の場合はトップレベルのクラス Cls1 とは別のものとなる

Module.nesting について, ドキュメントより引用.

  • このメソッドを呼び出した時点でのクラス/モジュールのネスト情報を配列に入れて返す
module Foo
  module Bar
    module Baz
      p Module.nesting   # => [Foo::Bar::Baz, Foo::Bar, Foo]
    end
  end
end

インスタンス変数の可視性

以下のコードで指定した行を書き換えた際に同じ結果になるものを選ぶ. (複数選択)

class Cls1
  def v=(other) # ここから
    @v = other
  end
  def v
    @v
  end           # ここまで
end

c = Cls1.new
c.v = 100
p c.v

以下, 解答.

# 解答 1
attr_reader :v
attr_writer :v

# 解答 2
attr_accessor :v

以下, irb にて確認.

# 設問
irb(main):001:0> class Cls1
irb(main):002:1>   def v=(other)
irb(main):003:2>     @v = other
irb(main):004:2>   end
irb(main):005:1>   def v
irb(main):006:2>     @v
irb(main):007:2>   end 
irb(main):008:1> end
=> :v
irb(main):009:0> 
irb(main):010:0* c = Cls1.new
=> #<Cls1:0x00564834342790>
irb(main):011:0> c.v = 100
=> 100
irb(main):012:0> p c.v
100
=> 100

# 解答 1
irb(main):001:0> class Cls1
irb(main):002:1>   attr_reader :v
irb(main):003:1>   attr_writer :v
irb(main):004:1> end
=> nil
irb(main):005:0> 
irb(main):006:0* c = Cls1.new
=> #<Cls1:0x00559c70e8ad70>
irb(main):007:0> c.v = 100
=> 100
irb(main):008:0> p c.v
100
=> 100

# 解答 2
irb(main):001:0> class Cls1
irb(main):002:1>   attr_accessor :v
irb(main):003:1> end
=> nil
irb(main):004:0> 
irb(main):005:0* c = Cls1.new
=> #<Cls1:0x00557406645710>
irb(main):006:0> c.v = 100
=> 100
irb(main):007:0> p c.v
100
=> 100

以下, 解説より抜粋.

  • attr_readerインスタンス変数を返すメソッド (def v\ end) を作成する
  • attr_writerインスタンス変数を変更するメソッド (def v=\ end) を作成する
  • attr_accessorインスタンス変数を返すメソッドと変更するメソッドを作成する

フムフム.