Ruby Goldへの道 day11
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
11日目 得点 64点/100点中
安定して70点を超えていたのに急に落ちた。 まだまだ理解が足りんな。
- 定数の参照は静的に行われる。継承を辿っていかない
module M CONST = "Hello, world" end class M::C def awesome_method CONST # 定数の参照はレキシカルに行われる # 継承を辿っていかない # M::CONST #=> "Hello, world" end end p M::C.new.awesome_method ##=> uninitialized constant M::C::CONST (NameError)
- class_eval
- ブロックを渡すとネストの状態はモジュールなのでモジュールの定数を参照
- 文字列を渡すとネストの状態はクラスなのでクラスの定数を参照
class C end module M CONST = "Hello, world" C.class_eval do # ブロックを渡すのでモジュールMに def awesome_method # モジュールMのCONSTを参照する CONST end end end p C.new.awesome_method #=> "Hello, world"
class C CONST = "Hello, world" end module M # 文字列を渡すのでネストの状態はクラスC # CクラスのCONSTを参照する C.class_eval(<<-CODE) def awesome_method CONST end CODE end p C.new.awesome_method
- Module#refine
- 引数で指定したクラスまたはモジュールに対してブロック内の機能を提供する
class C def m1 200 end end module R refine C do # Cクラスにm1メソッドを定義する # この場合m1メソッドをオーバーライドする def m1 100 end end end using R # モジュールRを有効化する c = C.new puts c.m1 #=> 100
Ruby Goldへの道 day10
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
10日目 得点 82点/100点中
- Hashオブジェクト
**オブジェクト
でオブジェクトの中身をキーワード引数に渡すことができる
def foo(arg1:100, arg2:200) puts arg1 puts arg2 end option = {arg2: 900} foo arg1: 200, *option # **optionでハッシュオブジェクトとして渡せる #=> syntax error, unexpected *
module A B = 42 def f 21 end end A.module_eval do p Module.nesting #=> [] # ネストされた状態ではない def self.f p B end end B = 15 A.f #=> 15 # トップレベルにある定数を指す
class Base # CONST = "Hello, world" # ②探索される # もしここにCONSTがなかったら18行目でPモジュールをprependしているのでPモジュールを探索する③ end class C < Base # ①探索される # Baseクラスを継承しているのでBaseクラスにCONSTがあるか探索する② end module P CONST = "Good, night" # ③探索される end class Base prepend P end module M class C CONST = "Good, evening" end end module M class ::C # トップレベルから定数の探索を行う def greet CONST # トップレベルのCクラスにCONSTの定数があるか探索する① end end end p C.new.greet #=> "Hello, world" p M::C::CONST #=> "Good, evening
Ruby Goldへの道 day9
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
9日目 得点 72点/100点中
後2問。 いつも前から問題をみて気になった問題を選んでいるが今日は気分転換に後ろから。
require 'yaml' yaml = <<YAML sum: 510, orders: - 260 - 250 YAML # 文字列のYAMLデータをハッシュオブジェクトにしている object = YAML.load yaml # YAMLデータをrubyオブジェクトにしている p object #=> {"sum"=>510, "orders"=>[260, 250]}
- singlten_class
- Object.singleton_classで特異クラスを取得することができる
class C def self._singleton class << C self # レシーバのオブジェクトを返す # ここでは class C end end end p C._singleton #=> #<Class:C> class C end p C.singleton_class #=> #<Class:C> p C.new.singleton_class #=> #<Class:#<C:0x00007fcfc5823998>>
class Array def succ_each(step = 1) return enum_for(:succ_each, step) unless block_given? # 引数が2つ 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" class Array def succ_each(step = 1) return to_enum(:succ_each) unless block_given? # 引数が2つ 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 #=> ["c", "d", "e"] #=> "j" #=> "k" #=> "l" class Array def succ_each(step = 1) return to_enum(:succ_each, step) unless block_given? # 引数が2つ 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"
Ruby Goldへの道 day8
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
8日目 得点 78点/100点中
今日も間違えた中から数問深掘りする
- ネストされたクラス内の定数の参照
class C p Module.nesting #=> [C] CONST = "Hello, class C" end module M class C p Module.nesting #=> [M::C, M] CONST = "Hello, module M class C" end end p C::CONST #=> "Hello, class C" p M::C::CONST #=> "Hello, module M class C"
- Module#refineは無名のモジュールをを作成する
- ブロック内のselfは無名モジュールになる
- クラスメソッドを再定義するには
singleton_class
を利用するself.メソッド
としない
class C def self.m1 200 end end module R refine C.singleton_class do def m1 # Cクラスのm1メソッドを再定義する # singleton_classがなければそのまま200が出力される 100 end end end using R puts C.m1 #=> 100
- 演算と戻り値のクラス
- 戻り値はRationalとFloatとComplex
- Rational < Float < Complexで覚えるといい
- Date同士の演算はRation
- Time同士の演算はFloat
- Datetime同士の演算はRational
val = 1 + 1/2r puts val.class #=> Rational puts 1.class #=> Integer # puts 1/2r.class #=> float = 1/3.to_f puts float.class #=> Float complex = 3.to_c puts complex.class #=> Complex val2 = float + complex puts val2.class #=> Complex
Ruby Goldへの道 day7
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
7日目 得点 76点/100点中
初の合格点。この調子で理解を深めていこう。 今日も間違えた中から数問深掘りする
- aliasとalias_method
- alias 新メソッド 旧メソッド の形で記述する。" , " は不要。
- alias_method :新メソッド, 旧メソッド の形で記述する。 " , " は必要。シンボル 型で記述できる
class String # aliasの場合 新メソッド 旧メソッド の形で記述する , はいらない alias hoge reverse # alias_methodの場合 :新メソッド, :旧メソッド の形で記述する alias_method :hoge, :reverse end p "12345".hoge
- prepend
- モジュールのメソッドを特異メソッドとして追加する
- メソッドの探索はselfより前に行われる
- 複数個記述した場合は左から探索される
module M1 end module M2 end class C prepend M1, M2 # selfより先に探索される。左から順に探索される。 end p C.ancestors #=> [M1, M2, C, Object, Kernel, BasicObject]
- includeはmoduleのインスタンスメソッドをMix-inする
- C.methodsはCの特異メソッドを表示する
module M def self.class_m "M.class_m" end end class C include M # MモジュールのインスタンスメソッドをMix-in end p C.methods.include? :class_m #=> false # Cにはclass_mは追加されない
Ruby Goldへの道 day6
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
6日目 得点 66点/100点中
停滞期に入ったな〜 70点の壁が厚い
今日から間違えた問題の深堀に方向転換
- class_eval
- ブロックを渡した場合は、ブロック内のネストはモジュールMになる
- 文字列を渡した場合のネストの状態はクラスCです。
# ブロックを渡した例 # ブロックはモジュールになるからMモジュールないのCONSTを探索 class C end module M CONST = "Hello, world" C.class_eval do def awesome_method CONST end end end p C.new.awesome_method #=> "Hello, world" # 文字列を渡した例 # ネストの中はクラスなのでCクラスのCONSTを探索 class C CONST = "Hello, world" end module M C.class_eval(<<-CODE) def awesome_method CONST end CODE end p C.new.awesome_method #=> "Hello, world"
- 特異クラス
- class << Hoge
- class << self
- def クラス.メソッド
の三パターンある 呼び出しはクラスメソッドと同じ クラス.メソッドで呼び出せる
class Hoge class << Hoge def hoge p '<< Hoge' end end class << self def hoge p '<< self' end end def Hoge.hoge p 'C.hoge' end end # 全てクラス.メソッドで呼び出せる Hoge.hoge #=> "C.hoge" # def Hoge.hoge..をコメントアウトすると Hoge.hoge #=> "<< self" # さらに<< self..をコメントアウトすると Hoge.hoge #=> "<< Hoge"
class C class << C # またはself def fuga #=> 特異メソッド 'Hi' end end def hoge #=> インスタンスメソッド 'Goodbye' end end # クラス内に定義したメソッドはインスタンスメソッド obj = C.new p obj #=> #<C:0x00007fb9128df8d8> p obj.hoge #=> 'Goodbye' p C.instance_methods(false) #=> [:hoge] p C #=> C # 特異メソッドの呼び出し # クラスメソッドの呼び出しと同じ p C.fuga #=> 'Hi'
Ruby Goldへの道 day5
以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp
5日目 得点 62点/100点中
昨日よりは落ちたけど半分は確実に超えるようになってきた。
- 特異クラスの呼び出しは
クラス.メソッド
class C class << C def hoge 'Hi' end end def hoge 'Goodbye' end end p C.new.hoge #=> "Goodbye" p C.hoge #=> "Hi"
- class << C ~ endの処理はクラスを定義した時点で実行される
class S @@val = 0 def initialize @@val += 1 end end class C < S class << C @@val += 1 end def initialize end end C.new C.new S.new S.new p C.class_variable_get(:@@val) #=> 3
- メソッド探索順はselfの後に追加される
module M def foo super puts "M#foo" end end class C2 def foo puts "C2#foo" end end class C < C2 def foo super puts "C#foo" end prepend M end C.new.foo #=> C2#foo #=> C#foo #=> M#foo
module M def foo super puts "M#foo" end end class C2 def foo puts "C2#foo" end end class C < C2 def foo super puts "C#foo" end prepend M end C.new.foo #=> C2#foo #=> C#foo #=> M#foo
- レキシカルスコープに定数がない場合は、スーパークラスの探索を行う
module M1 class C1 CONST = "001" end class C2 < C1 CONST = "010" module M2 CONST = "011" class Ca CONST = "100" end class Cb < Ca p CONST "011" # Cbに一番近いCONSTを探索する end end end end
- usingはRefinementを有効化しているがスコープ外は無効になる
class C def m1 400 end end module M refine C do def m1 100 end end end class C using M #=> スコープ外は無効 end puts C.new.m1
- const_getは、selfに定義された定数を探索する
class Human NAME = "Unknown" def self.name p self #=> Fukuzawa const_get(:NAME) # selfに定義されたクラスを探索する end end class Fukuzawa < Human NAME = "Yukichi" end puts Fukuzawa.name #=> Yukichi
- キーワード引数は省略できない
def foo(arg:) puts arg end foo 100 #=> wrong number of arguments (given 1, expected 0; required keyword: arg) (ArgumentError)
- Module.nestingはネストの状態を表示する
module SuperMod end module SuperMod::BaseMod p Module.nesting #=> [SuperMod::BaseMod] end module SuperMod module BaseMod p Module.nesting # [SuperMod::BaseMod, SuperMod] end end
- alias式はメソッドやグローバル変数に別名を付けることができる
class String # aliasの定義方法 alias new_method old_method alias :new_method :old_method alias $new_global_val $old_global_val end p "12345".hoge
- timesは0からself -1までの数値を順番に返す
10.times{|d| print d < 2...d > 5 ? "O" : "X" } #=> OOOOOOOXXX # 1. d < 2 が真を返すまでfalseを返す # 2. d < 2 が真を返すとtrueを返す # 3. 次は d > 5 を評価する # 4. d > 5 が真を返すまでtrueを返す # 5. d > 5 が真を返すとtrueを返して1に戻る
- prependで複数指定した場合右側から探索される
module M1 end module M2 end class C prepend M1, M2 end p C.ancestors #=> [SuperMod::BaseMod]
- 1iは複素数(Complex)のオブジェクト
val = 1i * 1i puts val.class #=> Complex
- initialize(*)とすることで、サブクラスで引数を意識する必要が無くなる
class S def initialize(*) puts "S#initialize" end end class C < S def initialize(*args) super puts "C#initialize" end end C.new(1,2,3,4,5) #=> S#initialize #=> C#initialize
会社からメタプログラミングrubyを借りてきたので明日はそれを読み進めよう 特異クラスとか気になっていた単語について調べよう