Ruby define_methodとclass_eval
# クラスを動的に定義 A = Class.new # #1 # Aクラスのコンテクストで # private_methodであるdefine_methodを使用 A.class_eval{ define_method(:hoge){|a| puts a } } A.new.hoge("hoge") #=> "hoge" # #2 # Aクラスのコンテクストで # private_methodであるdefine_methodを使用 A.__send__(:define_method,:fuga) {|a| puts a } A.new.fuga("fuga") #=> "fuga" # #3 # 動的に、クラスを定義し、メソッドを定義する方法例 # procは、Kernel#procを使用。受けたブロックをprocに変換して # __send__に送り、それを__send__はそのままdefine_methodへ送っている # わかりやすさという点でこうした方が良いか # def definer(class_name,method_name,&k) # class_name=Object.const_set(class_name.capitalize,Class.new) # class_name.__send__(:define_method,method_name,k) module A def definer(class_name,method_name) class_name=Object.const_set(class_name.capitalize,Class.new) class_name.__send__(:define_method,method_name,proc) end end class B extend A end B.definer("C",:hoge) {|a| puts a } C.new.hoge(1)
こういった臨機応変にクラスやメソッドを動的定義、追加することは、リフレクションプログラミングという。 見通しは悪くなるが柔軟。
Ruby 定数の参照順位 - Silver/Gold試験対策
定数は外側を参照し、その次に継承関係を探索する
class C CONST = "c" end class A CONST = "a" class B < C p CONST end end #=> "a"
このように明示的に、定数を参照することもできる
class C CONST = "c" end class A CONST = "a" class B < C p C::CONST end end #=> "c"
CONST = "d" class A p CONST end #=> "d"
トップレベルは参照順位が低い
CONST = "d" class A CONST = "e" end class B < A p CONST end #=> "e"
参照先をトップにすると
CONST = "d" class A CONST = "e" end class B < A p ::CONST end #=> "d"
Ruby Fiber - Silver/Gold試験対策
概要
- Fiberは、ノンプリエンプティブ(nonpreemptive)なタスクスケジューリング方式。
- Threadはプリエンプティブ(preemptive)。プリエンプティブとは先制、先取の意味がある。
- プリエンプティブである、Threadだと、例外が発生したりすると、勝手にスレッドが切り替わる。
- このThreadの挙動はこれは適切で、無限ループをわかっていながら実行し続けたりせずというOSなどもっとRawなコントロールにスケジュールを任せようということだと思う。 一方、Fiberは明示的にタスクを受け渡し宣言をすることでアプリケーションレベルでタスクスケジュールを管理できるようだ。
詳細
- resumeとはFiberのあるブロックの実行を続行(文字通りresume)する
- yieldとはFiberのブロックから、resumeした親にコンテクストを預けるというか、処理をsuspendするイメージ
f = Fiber.new do p "hoge" Fiber.yield p "fuga" end f.resume #=> "hoge" f.resume #=> "fuga"
- yieldは引数と共に、コンテクストをresumeに預ける。Fiber#resumeの返り値はその引数
f = Fiber.new do n = 3 loop do Fiber.yield(n) n += 1 end end p f.resume #=> 3。 p f.resume #=> 4。一度めのyieldの後ろを実行し、loopして、2度めのyieldで引数と共にコンテクストを返してもらう
親に例外が伝播する
f = Fiber.new do raise StandardError, "StandardError in Fiber" end begin f.resume rescue => ex p ex.message #=>"StandardError in Fiber" end
実行するFiberがない場合はFiberErrorに。
f = Fiber.new do "fiber" end p f.resume #=> "fiber" p f.resume #=> FiberError
Ruby rdoc - Silver/Gold試験対策
#= "#="で見出し1 #== "#=="見出し2 #=== "#==="さようなら #- "#-"箇条書き1 #- "#-"箇条書き1 #* "#*"箇条書き別の方法 #* "#*"箇条書き別の方法 #1. "#1."箇条書き数字 #2. "#2." #a. "#a."箇条書きアルファベット小文字 #b. "#b." #A. "#A."箇条書きアルファベット大文字 #B. "#B." #C. "#C." #[cat] \[cat\]でラベル付き #dog:: \dog::でもラベル付き #*birds*:: \*birds\*で太字 #_italic_:: \_italic\_ #[罫線] #\-\-\-で罫線 #--- class A include M def hoge :hoge end def self.fuga end end
プレビュー
Ruby Object Class - Silver/Gold試験対策
Ruby 定数の参照順番 - Silver/Gold試験対策
定数は自クラスを参照し、その後、外側のクラスを参照する
class C1 MSG = "msg1" MSG2 = "msg2" class C2 MSG = "C2:msg1" puts MSG #=> C2:msg1 puts MSG2 #=> msg2 end puts MSG #=> msg1 puts MSG2 #=> msg2 end
MSG3=1 class A puts MSG3 #=> 1 end
Ruby DATA __END__ - Silver/Gold試験対策
DATAとEND。全て大文字
while DATA.gets puts $_ if $_ =~ /Ruby/ end #=> Ruby the prgoramming language __END__ Java the prgoramming language Ruby the prgoramming language Python the prgoramming language
下記とほぼ同じ
DATA.each do |str| puts str if str =~ /Ruby/ end __END__ Java the prgoramming language Ruby the prgoramming language Python the prgoramming language
String#=~とRegexp#=~があるので、 selfが文字列、otherが正規表現の場合だけでなくその逆でもマッチが検査できる
self =~ other