åå ã¯åãªãã¸ã§ã¯ãã®åºæ¬çãªç¹å¾´ãè¦ãã ãã§çµãã£ã¦ãã¾ã£ããä»åã¯ããããã³ã³ããã¹ãã¨ãã観ç¹ããè¦ã¦ã¿ããã
ååã®ã¾ã¨ã
å¼ã³åºã | å¤å´ã®scope | block | ä¸èº« | æ»ãå¤ | |
---|---|---|---|---|---|
__send__ | __send__ | ä¸å¯è½(ããããã³ã³ããã¹ããä¿åãã¦ããªã) | å¯è½ | ä¿æããªã | ã¡ã½ããã®æ»ãå¤ |
Method | [] ,call | åç §ä¸å¯è½ | å¯è½ | ã¡ã½ããæ¬ä½ã¨self | ã¡ã½ããã®æ»ãå¤ |
UnboundMethod | ä¸è½ | åç §ä¸å¯è½ | - | æ¬ä½ | ã¡ã½ããã®æ»ãå¤ |
Proc | [] ,call ,yield | åç §å¯è½ | ä¸å¯è½ | closure | Procã®æå¾ã®å¤ |
Continuation | [] ,call | - | ä¸å¯è½ | ãç¶ãã | æ»ããªã |
Proc#callã«ããã¦ãããã¯ä»ãã®å¼ã³åºããä¸å¯è½ã§ãããã¨ã¯ååã¯è¨è¿°ããªãã£ãã sshiããã«ãææããã ãã ã
Procãä½æããã¨ãã«æå®ãããããã¯ä»®å¼æ°ã®è¨è¿°ã¯ãã¡ã½ããå®ç¾©ã®éã®ä»®å¼æ°ã®è¨è¿°ã«ã¨ã¦ãä¼¼ã¦ããã
adder = Proc.new{|a, b| a + b} # æ®éã®å¼æ° sum = Proc.new{|*elements| elements.inject(0, sum){|elem| sum + elem} } # *ãã¤ããã°ä»»æåã®å¼æ°ãé åã¨ãã¦åãåãã
ãªãã°ã&ãä»ããã°ãããã¯å¼æ°ãåãåããããªãã®ã ãããã©ããå®éã«ã¯ããã¯æ§æã¨ã©ã¼ã¨ãªãã
Proc.new{|a, b, &block| :ok } # => parse error, unexpected tAMPER
Procãä½ãã«ã¯ãããã¯ãå¿ è¦ã ããã©ããããããããã¯æ§æãã®ãã®ããããã¯ãåãä»ããããã«ã§ãã¦ããªãããããã¯ä»ãå¼ã³åºãã«æ´ã«ãããã¯ãä»ããã¨ããã®ã¯å¤ã ããæ®éã¯å°ããªãã®ã ããã©ã
ä½ãããªã·ã¼ããã£ã¦ãããã¯ãåãProcã®å¯è½æ§ãå¼¾ãã¦ããã®ãã©ããã¯åãããªãã2006-11-20追è¨: ã¾ã¤ãã¨ãããããææããã ãã¾ãããRuby 1.9ã§ã¯Proc#callã¯ãããã¯ãã¨ããããã§ãã
ã¨ãããããã§ãä»åã®æ¬é¡ã«å ¥ãã
ç¸äºå¤æ
ã¡ã½ãããMethodãªãã¸ã§ã¯ããUnboundMethodãªãã¸ã§ã¯ãããããã¯ãProcãªãã¸ã§ã¯ããContinuationãªãã¸ã§ã¯ãã¯ç¸äºã«å¤æãå¯è½ã§ããããã ããå¤æã¨ãã£ã¦ãããããã«ç¹å¾´ããããªãã¸ã§ã¯ãã ãããå®å ¨ã«å¤æå ã«ãªããã£ã¦ãã¾ãããã§ã¯ãªãããã£ã¨ãããªããã£ã¦ãã¾ã£ããé¢ç½ããªããå¤æã®çµæã¨ãã¦ãããã¯ã®ãããªã¡ã½ãããMethodãªãã¸ã§ã¯ãã®ãããªProcãçã¾ããããå³ãããã®ã§ããã
ã¡ã½ããã®ä½æ
ã¡ã½ããã¯æ®éã¯defæã§ä½ãã®ã§ãã£ããRubyã«ã¯ãã1ã¤ã¡ã½ãããä½ãæ¹æ³ããããModule#define_methodã§ããã
define_method(name, method) define_method(name) { ... }
ãã®ã¡ã½ããã¯ç¬¬2å¼æ°ã«Method, UnboundMethod, Procã®ããããã渡ãããããã¯ãããã¯ä»ãã§å¼ã³åºãã¦ä½¿ããããã«ããMethod, UnboundMethod, Proc, ãããã¯ãã¡ã½ããã«å¤æã§ãã訳ã ã
ãã£ã¨ããMethod, UnboundMethodã®ã»ãã¯ãã¾ã便å©ã¨ã¯æããªããåå触ããMethodã¨Unboundã®å¤æã¨åæ§ã§ãç°ãªãã¯ã©ã¹ã«ã¯ã¡ã½ããã移ããªãããã ã *1
ãããã¯ä»ãã§å¼ã³åºããå ´åã¯ãããã¯ã¯Procãªãã¸ã§ã¯ãã«å¤æããã¦ããå¦çããããã ããã次ã®2ã¤ã¯åããã¨ã ã
define_method(:foo) do |a, b, c| p [a, b, c] end define_method(:foo, lambda{|a,b,c| p [a, b, c] })
ããã§é¢ç½ãã®ã¯Proc(ãããã¯ãããã¯)ã渡ããå ´åã«ã¯ããããæã£ã¦ããå¤é¨ã¹ã³ã¼ãã¸ã®åç §ããã®ã¾ã¾çããã¨ãããã¨ããããç¨ãããã¨ã§ãã¯ã©ã¹å®ç¾©æã®ãã¼ã«ã«å¤æ°ãåç §ãããããªã¡ã½ãããå®ç¾©ã§ããã
class Hoge local = 1 define_method(:foo) do p local += 1 end define_method(:bar) do p local += 1 end end
ç§ããããã¯ä»ãã®define_methodãç¨ããã®ã¯ãã£ã±ããã®å½¢ã ãdefæã¨éã£ã¦å¤å´ã®å¤æ°ã¹ã³ã¼ããåç §ã§ããã®ã§ä½ãã¨ä¾¿å©ã ãããããã¦æããããã¼ã«ã«å¤æ°ã¸ã®åç §ã¯ãä¸åº¦ã¯ã©ã¹å®ç¾©æãæãã¦ãã¾ã£ããå¤é¨ããã¯åç §ã§ããªãã®ã§ãµãã¯ã©ã¹ã®å®è£ ã¨ååãè¡çªããå¿é ããªãã
ã¯ã©ã¹æã®ä¸ããã¯å¤ã®ã¹ã³ã¼ããåç §ã§ããªãã®ã§æ¬¡ã®ããã«æ¸ãã¨NameErrorãçãã
local = 1 class Hoge define_method(:foo) do local end end hoge = Hoge.new hoge.foo # => NameError: undefined local variable or method `local' for #<Hoge:0x6e28>
ããã©ããclass_evalãç¨ããã°å¤å´ãåç §å¯è½ã§ããã
class Hoge; end local = 1 Hoge.class_eval do define_method(:foo) do local end end
ãã®ããããã¯ååå®ç¾©ããsingleton_class_evalã¨çµã¿åãããã¨ã¡ã½ããå ã§ç¹ç°ã¯ã©ã¹ãçæããéã«ä¾¿å©ã ããã¹ãç¨ã«ç°¡æãªMockãä½æãããªã©ã®éã«éå®ããã
def test_foo received_args = [] # ããã«æ¸¡ãããå®å¼æ°ã®å¤ããã¾ã mock = Object.new mock.singleton_class_eval do define_method(:callback) do |*args| received_args << args end end testee(mock) # ãã¹ããããã¡ã½ãã # ãããmock.callbackãå¼ã¶ã¯ã assert_xxx ... end
Methodãªãã¸ã§ã¯ãã®ä½æ
Methodãªãã¸ã§ã¯ãã¯ååè¿°ã¹ãããã«ãã¡ã½ãããå ã«ãã¦Object#methodã§ä½æããã®ã§ãã£ãããã®ã»ããUnboundMethod#bindã§ãä½æã§ããã
UnboundMethodã®ä½æ
UnboundMethodã¯ã¡ã½ãããå ã«ãã¦Module#instance_methodãç¨ããããMethod#unbindãç¨ããã®ã§ãã£ãã
ãããã¯ã®ä½æ
ãããã¯ã¯æä½ã®å¯¾è±¡ã¨è¨ãããã¯æ§æã®å½¢ã ãããããèªä½ãããã°ã©ã ä¸ã§ä½æããæ¹æ³ã¨ããã®ã¯ãªããããã©ãããããã¯ä»ãå¼ã³åºãã®ä»£ããã«Procãªãã¸ã§ã¯ãã«&ãä»ãã¦å¼ã³åºããã¨ã¯ã§ããã®ã§ãã£ãã次ã®2ã¤ã¯ã»ã½ç価ã§ããã
collection.each do |item| p item end proc = Proc.new{|item| p item} collection.each(&proc)
Procãªãã¸ã§ã¯ãã®ä½æ
Procãªãã¸ã§ã¯ãã¯ãããã¯ãå ã«ãã¦Proc.newã¾ãã¯Kernel#lambdaã§ä½ãã®ãåºæ¬ã§ãã£ãã
ãã®ã»ããMethodã¯to_procã¡ã½ãããæã£ã¦ãããProcã¸ã®å¤æãå¯è½ã§ããã
proc = hoge.method(:foo).to_proc proc.is_a? Proc # => true
Continutationãªãã¸ã§ã¯ãã®ä½æ
Continuationã¯Kernel#callccã«ãããã¯ã渡ãã¨ä½æã§ããã®ã§ãã£ããããããã¯æ¸¡ãããããã¯ãå ã«ä½æãããã¨ã¯è¨ããªãããã®ãããã¯ã¯Continuationãªãã¸ã§ã¯ããåãåãåãç¿ã¨ãã¦ä½¿ãããã®ã§ãããContinuationãªãã¸ã§ã¯ãã®å ã«ãªã£ã¦ããã®ã¯ãcallcc以éã®å¦çãã§ãã£ãã
ç¸äºé¢ä¿
以ä¸ãå³ã«ããã¨æ¬¡ã®ããã«ãªããContinuationã¯ãã¯ãç¹æ®ãªã®ã§é¤ãã¦ããã
ã³ã³ããã¹ã
ä¸ã®å³ãè¦ã¦ãã¡ã½ãã -> Method -> Proc -> ã¡ã½ãããã®ãããªãµã¤ã¯ã«ãåå¨ãããã¨ãåããã¨æãããªãã°ããããã¨ãµã¤ã¯ã«ãåãã¦ã¿ããã©ããªããã¨æãã®ã人æ ã¨ãããã®ã ãã§ããã¡ãã£ã¨å ã«ã³ã³ããã¹ãã®è©±ãããã¦æ¬²ããããã®ãµã¤ã¯ã«ã¯ã³ã³ããã¹ãã¨ãã観ç¹ããè¦ãæ¹ã楽ãããã
ã³ã³ããã¹ãã¨ã¯ãããã£ã±ã«è¨ãã°ãã¼ã«ã«å¤æ°ã®ç¶æ ãself, klassããæãã
ããã§ãã¼ã«ã«å¤æ°ã¨ããã®ã¯ãåç §ã§ããéãå¤å´ã®ã¹ã³ã¼ããå«ããå ¨é¨ã ãselfã¨ããã®ã¯ããã©ã«ãã§ã¡ã½ãããåãåãç¸æã§ãããRubyã®ããã°ã©ã ã«ã¯ãã¤ã§ãselfããã¦ãæ¬ä¼¼å¤æ°selfãéãã¦ã¢ã¯ã»ã¹ã§ããã®ã§ãã£ããklassã«ã¤ãã¦ã¯å¾è¿°ãä»ã¯å¿ãã¦ããã¦è¯ãã
ã³ã³ããã¹ãã¨ãããã®ãèãã«å ¥ãã¦ã¿ãã¨ãåå¼ã³åºãå¯è½ãªãã¸ã§ã¯ãã¯æ¬¡ã®ãããªãã®ã§ããã¨ãããã
Method
ã¡ã½ããå®ç¾©ã®æ¬ä½ + self
UnboundMethod
ã¡ã½ããå®ç¾©ã®æ¬ä½
Proc
ãããã¯ã®æ¬ä½ + ã³ã³ããã¹ã
Continuation
å®è¡ã³ã¼ãæ¬ä½ + ã³ã¼ã«ã¹ã¿ã㯠+ ã³ã³ããã¹ã
ã¡ãªã¿ã«ãã³ã³ããã¹ãã ãã表ãã¦æ¬ä½ã®ã³ã¼ãã¯æããªãã®ã Binding ã§ãããCè¨èªã¬ãã«ã§ã¯Procã¨Bindingã¯ã©ã¡ããstruct BLOCKãå©ç¨ãã¦å®è£ ããã¦ããã
Procãã³ã³ããã¹ããæã£ã¦ãã証æ ãè¦ã¦ã¿ããã
class Original CONST = :original $global = :original @@class = :original def create_proc @instance = :original local = :original return Proc.new { p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local } end def modify @instance = :modified local = :modfied end CONST = :modified $global = :modified @@class = :modified end class Other CONST = :other @@class = :other $global = :other def call(method) local = :other @instance = :other method.call end end orig = Original.new proc = orig.create_proc orig.modify # ã¤ã³ã¹ã¿ã³ã¹å¤æ°ãå¤æ´ãã¦ãã¾ãã # é¢ä¿ãªãã®ãèªæã ããã©ãããã¼ã«ã«å¤æ°ãã other = Other.new other.call proc
ãããå®è¡ããã¨æ¬¡ã®ããã«ãªã
caller | ["proc.rb:42:in `call'", "proc.rb:52"] |
self | #<Original:0x2466c @instance=:modified> |
__FILE__ | "proc.rb" |
__LINE__ | 14 |
CONST | :modified |
$global | :other |
@@class | :modified |
@instance | :modified |
local | :original |
- æ¬ä¼¼å¤æ°self, FILE, LINEããã³ãã¼ã«ã«å¤æ°ã¯Procä½ææã®ãã®ããã®ã¾ã¾æ®ã£ã¦ããã
- å®æ°ãã¯ã©ã¹å¤æ°ãã¤ã³ã¹ã¿ã³ã¹å¤æ°ã¯ä½æå¾ã®å¤æ´ãåæ ããã¦ããããæ¢ç´¢ã¯Procä½ææã®å ´æããè¡ããã¦ãããå¼ã³åºãæã®selfã¯é¢ä¿ãªã
- ã°ãã¼ãã«å¤æ°ã¯æå¾ã®å¤æ´ãåæ ããã¦ããããããããã ã
ãããããå®æ°ãã¯ã©ã¹å¤æ°ãã¤ã³ã¹ã¿ã³ã¹å¤æ°ãã°ãã¼ãã«å¤æ°ã¯ã³ã³ããã¹ãã¨ãã¦ä¿åãããããã§ã¯ãªãã¨ãããã¨ãåããããããã¯selfãéãã¦éæ¥çã«ã¢ã¯ã»ã¹ãããã
åæ§ã«Continuationãè¦ã¦ã¿ããã
class Original CONST = :original $global = :original @@class = :original def create_cc @instance = :original local = :original callcc{|c| return c} p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local end def modify @instance = :modified local = :modfied def create_cc # ã¡ã½ãããä¸æ¸ã raise end end CONST = :modified $global = :modified @@class = :modified end class Other CONST = :other @@class = :other $global = :other def call(cc) local = :other @instance = :other cc.call end end orig = Original.new cc = orig.create_cc orig.modify # ã¤ã³ã¹ã¿ã³ã¹å¤æ°ãå¤æ´ãã¦ãã¾ãã # é¢ä¿ãªãã®ãèªæã ããã©ãããã¼ã«ã«å¤æ°ãã if cc other = Other.new other.call(cc) end
å®è¡çµæã¯æ¬¡ã®éãã§ããã
caller | ["continuation.rb:50"] |
self | #<Original:0x244b4 @instance=:modified> |
__FILE__ | "continuation.rb" |
__LINE__ | 14 |
CONST | :modified |
$global | :other |
@@class | :modified |
@instance | :modified |
local | :original |
ã³ã³ããã¹ããä¿åããã¦ããã®ã¯åãã ããcallerã®çµæãè¦ãã¨ã³ã¼ã«ã¹ã¿ãã¯ã復å ããã¦ãããã¨ãåãããæ´ã«ãã¡ã½ããã®å®è£ (æ¬ä½)ãæ¸ãæãåã®ãã®ã使ç¨ããã¦ããã
ã¾ã¨ããã¨ããã®ããã«ãªãã
ãã¼ã«ã«å¤æ° | self | æ¬ä½ | ã³ã¼ã«ã¹ã¿ã㯠| |
---|---|---|---|---|
__send__ | åç §ä¸è½ | å¼ã³åºãæ | å¼ã³åºãæ | å¼ã³åºãæ |
Method | åç §ä¸è½ | ä½ææ | ä½ææ | å¼ã³åºãæ |
UnboundMethod | åç §ä¸è½ | ãªã | ä½ææ | å¼ã³åºãæ |
Proc | ä½ææ | ä½ææ | ä½ææ | å¼ã³åºãæ |
Continuation | ä½ææ | ä½ææ | ä½ææ | ä½ææ |
ã³ã³ããã¹ãã®ããæ¿ã
Rubyã«ã¯ã³ã³ããã¹ããããæ¿ããã¡ã½ãããããã¤ããããevalæã¨å¼ã°ãã Kernel#eval, Object#instance_eval, Module#module_eval, Binding#evalã§ããã
ã¾ããdefine_methodãã³ã³ããã¹ãå·®ãæ¿ãã¡ã½ããã®ä¸ç¨®ã¨è¦ããã¨ãã§ããã
Kernel#eval
eval(expr[, binding[, fname[, lineno=1]]])
evalé¢æ°ã¯evalæã®ä»£è¡¨æ ¼ã§ãããç§ã¯ãã¾ã使ããªãããPerlã¨éã£ã¦ä¾å¤å¦çã«evalã使ããã«çµã¿è¾¼ã¿ã®ä¾å¤æ©æ§ã使ãã¨ããã®ã大ããããã©ãã¡ãªã¿ã«ãRubyã®evalã¯ãããã¯ãåããªããæååãããã°ã©ã ã¨ãã¦å®è¡ããã®ã¿ã§ããã
evalé¢æ°ã¯ããã©ã«ãã§ã¯ç¾å¨ã®ã³ã³ããã¹ãã§æååexprãRubyããã°ã©ã ã¨ãã¦ã³ã³ãã¤ã«ããå®è¡ãããbindingãä¸ããããã¨bindingãå é¨ã«æã£ã¦ããã³ã³ããã¹ããå©ç¨ãããBindingã¯ã©ã¹ã¯ä¸»ã¨ãã¦ãã®ç¨éã®çºã«è¨ãããã¦ããã¯ã©ã¹ã ã
fnameãlinenoãä¸ããã¨ãã¡ã¤ã«åãè¡çªå·æ å ±ããã®å¤ã«å·®ãæ¿ãããããããè¦ã¦ã¿ããã
class Original CONST = :original $global = :original @@class = :original def create_binding @instance = :original local = :original return binding # Kernel#binding end def modify @instance = :modified local = :modfied end CONST = :modified $global = :modified @@class = :modified end class Other CONST = :other @@class = :other $global = :other def call(program, binding) local = :other @instance = :other eval(program) puts eval(program, binding) puts eval(program, binding, __FILE__) puts eval(program, binding, __FILE__, __LINE__) end end orig = Original.new binding = orig.create_binding orig.modify # ã¤ã³ã¹ã¿ã³ã¹å¤æ°ãå¤æ´ãã¦ãã¾ãã # é¢ä¿ãªãã®ãèªæã ããã©ãããã¼ã«ã«å¤æ°ãã other = Other.new other.call <<'EOS', binding p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local EOS
ãããå®è¡ããã¨æ¬¡ã®ããã«ãªã£ãã
1 | 2 | 3 | 4 | |
---|---|---|---|---|
caller | ["eval.rb:51:in `eval'", "eval.rb:32:in `call'", "eval.rb:51"] | ["eval.rb:10:in `create_binding'", "eval.rb:46"] | ["eval.rb:10:in `create_binding'", "eval.rb:46"] | ["eval.rb:10:in `create_binding'", "eval.rb:46"] |
self | #<Other:0x245cc @instance=:other> | #<Other:0x245cc @instance=:other> | #<Original:0x24644 @instance=:modified> | #<Original:0x24644 @instance=:modified> |
__FILE__ | "(eval)" | "eval.rb" | "eval.rb" | "eval.rb" |
__LINE__ | 4 | 13 | 4 | 44 |
CONST | :other | :modified | :modified | :modified |
$global | :other | :other | :other | :other |
@@class | :other | :modified | :modified | :modified |
@instance | :other | :modified | :modified | :modified |
local | :other | :original | :original | :original |
ãã ãã1-4ã¯é ã«
eval(expr)
eval(expr, binding)
eval(expr, binding, fname)
eval(expr, binding, fname, lineno)
å½ããåã ããæååã¨ãã¦æ¸ãããããã°ã©ã ã¯ãã ã®æååã§ããä¸åã®ã³ã³ããã¹ããä¿æãã¦ããªãããã®ãããevalå®è¡æã®ã³ã³ããã¹ãããã®ã¾ã¾åæ ããã¦ããããã ããFILEã¯"(eval)"ã§ãããLINEã¯evalæååå ã®è¡çªå·ã§ããã
2çªç®ãè¦ãã¨Bindingãã³ã³ããã¹ããä¿æãã¦ããã®ãåããã¨æããbindingä½ææã®ã³ã³ããã¹ãã«ããæ¿ãã£ã¦ããã
3çªç®ã§ã¯ãã³ã³ããã¹ãã¯bindingã«å¾ããããã¡ã¤ã«åã ããå¼æ°fnameã«æå®ãããã®ã«å¤ãã£ã¦ãããæå¤ã ã£ãã®ã¯ãLINEã ãbindingã®æã£ã¦ããLINEã§ã¯ãªããevalæååå ã®è¡çªå·ã«æ»ã£ã¦ãã¾ã£ã¦ãããæ®éfnameãæå®ãããªãä¸ç·ã«linenoãæå®ããããä»ã¾ã§æ°ã¥ããªãã£ãããè¨ããã¦ã¿ãã°ããã§è¡çªå·ã ãbindingã«å¾ã£ã¦ãããã£ã¦æ··ä¹±ãããããããªãã
4çªç®ã§ã¯ãæå¾ éãfnameã¨linenoãåæ ããã¦ããã
fname, linenoã¯ã¹ã¿ãã¯ãã¬ã¼ã¹åºåã親åã«ããããã®ãã®ã ãä¾ãã°evalå ã§ã¡ã½ãããå®ç¾©ãããããã¨ããã¹ã¿ãã¯ãã¬ã¼ã¹ã«"(eval)"ã®12è¡ç®ã¨ãæ¸ãã¦ãã£ã¦ã該å½ããã½ã¼ã¹ãã©ãã«ããã®ãåãããã«å°ã£ã¦ãã¾ããããã§ãevalå®è¡æã«fnameã¨linenoãã渡ããæååãªãã©ã«ã®è¿ãããã¤ã³ãããããã«ä¸ãã¦ããã°ãä¾å¤çºçæã®ãã³ãã«ãªãã
ä¾ãã°ã次ã¯booleanå±æ§ã®ããã®attr_accessorã®å¤ç¨®ã§ãããæååã§ä¸ããããã¡ã½ããå ã§ä¾å¤ãçããã¨ããã¹ã¿ãã¯ãã¬ã¼ã¹ã«evalã®è¡ãè¨ããã¦ããã®ã§ã¨ããããattr_booleanã¾ã§ã¯ãã©ã£ã¦ãããã¨ãã§ãããããã§ã¯ãBindingã¯Kernel#bindingã«ãã£ã¦ãã®å ´ã§ä½æãã¦ããã
def attr_boolean(name) eval <<-"EOS", binding, __FILE__, __LINE__ def #{name}? @name != false end def #{name}=(value) @name = value end EOS end
Binding#eval
Binding#evalã¯Ruby 1.9ã§å°å ¥ããããæ©è½çã«ã¯Kernel#evalã¨å¤ãããªãã次ã®2ã¤ã¯ç価ã§ããã
eval(expr, binding, fname, lineno)
binding.eval(expr, fname, lineno)
åè¨ã®attr_booleanã®ããã«Bindingããã®å ´ã§ä½æããã®ã§ã¯ãªããäºãã©ããã§ä½ããã¦ããBindingãªãã¸ã§ã¯ããå©ç¨ããã¨ãã¯Binding#evalã®ã»ããèªç¶ãªè¡¨è¨ã®æ°ãããã
Object#instance_eval
Object#instance_evalã¯ãselfã®å·®ãæ¿ããã«ä½¿ãããã®ã¡ã½ããã«ã¯æååå½¢å¼ã¨ãããã¯å½¢å¼ãããã
instance_eval(expr, [fname, [lineno=1]]) instance_eval {|obj| ... }
ãããã«ãã¦ããä¸ããããæååããããã¯ãinstance_evalã®ã¬ã·ã¼ãã¼ã®ã³ã³ããã¹ãã§å®è¡ããããã ãããããã¯ã®å ´åããã¼ã«ã«å¤æ°ã ãã¯ãã¨ã®ã³ã³ããã¹ãã®ã¾ã¾ã ã
次ã®ããã°ã©ã ãå®è¡ãã¦ã¿ãã
class Original CONST = :original $global = :original @@class = :original end class Original def create_proc @instance = :original local = :original return Proc.new{ p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local } end def modify @instance = :modified local = :modfied end const_set("CONST", :modified) $global = :modified @@class = :modified end class Other CONST = :other @@class = :other $global = :other def call(str, proc) local = :other @instance = :other self.instance_eval(str) puts self.instance_eval(&proc) end end orig = Original.new proc = orig.create_proc orig.modify # ã¤ã³ã¹ã¿ã³ã¹å¤æ°ãå¤æ´ãã¦ãã¾ãã # é¢ä¿ãªãã®ãèªæã ããã©ãããã¼ã«ã«å¤æ°ãã other = Other.new other.call <<'EOS', proc p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local EOS
çµæã¯ãããªãã
æååç | ãããã¯ç | |
---|---|---|
caller | ["instance_eval2.rb:56"] | ["instance_eval2.rb:46:in `call'", "instance_eval2.rb:56"] |
self | #<Other:0x242d4 @instance=:other> | #<Other:0x242d4 @instance=:other> |
__FILE__ | "(eval)" | "instance_eval.rb" |
__LINE__ | 4 | 15 |
CONST | :other | :modified |
$global | :other | :other |
@@class | :other | :modified |
@instance | :other | :other |
local | :other | :original |
æååã¯ãã¯ãããèªä½ã¯ã³ã³ããã¹ããæã£ã¦ããªãããå ¨é¨otherã®ã¤ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãã«ãªã£ã¦ããããã®å ´åfnameãlinenoã¯æ¸¡ãã¦ããªãã®ã§FILEãLINEã¯evalæååã®ãã®ã ã
Procã渡ããå ´åãèå³æ·±ãããã¡ã¤ã«åãè¡çªå·ããã¼ã«ã«å¤æ°ãè¦ãã¨ã³ã³ããã¹ãã¯ä¿åããã¦ãããã¨ãåããããselfã¨ããããé£åãã¦ã¤ã³ã¹ã¿ã³ã¹å¤æ°ã¯otherã®ãã®ã«å¤ãã£ã¦ãããä¸æ¹ãå®æ°ãã¯ã©ã¹å¤æ°ã¯Originalã®ãã®ãåç §ãã¦ãããselfã ããå·®ãæ¿ããã®ã ã
instance_evalã«æ¸¡ãããããã¯ãè©ä¾¡ããã¨ãã«ã¯instance_evalã®ã¬ã·ã¼ãã¼ãselfã«æã£ã¦ãããã¨ãããã¨ã¯privateã¡ã½ãããã¤ã³ã¹ã¿ã³ã¹å¤æ°ã«å¤ããã¢ã¯ã»ã¹ã§ãããããããä»ã®ã¹ã³ã¼ãã®ãã¼ã«ã«å¤æ°ã¯å¤ãããã¢ã¯ã»ã¹ã§ããã¨ãããã¨ã ã
class Foo def initialize @hidden = 1 end private def hidden 99 end end foo = Foo.new local = 10 foo.instance_eval do p @hidden + local p hidden + local end
ããã©ãããããªã®ã¯instance_evalã®ä¸çªã¤ã¾ããªã使ãæ¹ã«éããªããselfã®å·®ãæ¿ãããã¾ãæ´»ããã¦ããã®ãRuby/Tkã§ããã
TkButton.new do text 'OK' command proc{exit} pack end
ã¾ãã§è¨å®ãã¡ã¤ã«ã§ãå¼ãã§ãããã®ããã ãã¯ããã®è¨ãæ¹ããããªãè¨èªå DSLã§ãããå¿è«ãtextã¨ãcommandãªã©ã¨ããã¡ã½ãããKernelã«å®ç¾©ããã¦ããããã§ã¯ãªãããããã¯TkButtonãªãã¸ã§ã¯ãã®ã¡ã½ããã ãRuby/Tkã¯selfãå·®ãæ¿ãã¦ãã®ãããªè¨è¿°ãå¯è½ã¨ãã¦ããã®ã§ããã
ç§ã¯Rakeããããããããæ¹ãããã°ããã£ãã®ã«ãã¨æã£ã¦ããã Rakeã®ã¿ã¹ã¯å®ç¾©ã¯æ¬¡ã®ãããªã®ãã決ã¾ãã®æ¸ãæ¹ã ã
Rake::TestTask.new(:test) do |t| t.libs << 'lib' t.pattern = 'test/**/*_test.rb' t.verbose = true end
ãã®"t."ã¯éªéã§ã¯ç¡ãããããç§ã¯ããæ¸ãããã
Rake::TestTask.new(:test) do libs << 'lib' pattern 'test/**/*_test.rb' verbose true end
Rakeã®åææ§æ³æ®µéã§ã¯ã©ãããããããæ§æã ã£ããããããã©ãé²åã®éç¨ã§ä½æ ãä½è¨ãªãããã¯å¼æ°ãä»ãã¦ãã¾ã£ã¦ããã確ãã«selfãå·®ãæ¿ããã¨ãããã¯ã®å¤å´ã§ã¯ã¢ã¯ã»ã¹ã§ãã¦ããã¤ã³ã¹ã¿ã³ã¹å¤æ°ãã¡ã½ããã«ã¢ã¯ã»ã¹ã§ããªããªãã¨ããå¼å®³ãããããã©ããæ®éã¯Rakeã®ã¿ã¹ã¯å®ç¾©ãã¤ã³ã¹ã¿ã³ã¹ã¡ã½ããã§å®è¡ããªãã ããããªããæ®éã®Rakefileãæ¸ãã¶ãã«ã¯ä¸ã®æ¸ãæ¹ã®ã»ããç¾ããã§ã¯ãªããã
module_eval
module_evalã¯Moduleã®ã¡ã½ããã§ãããaliasã¨ãã¦class_evalã¨ããã®ãå®ç¾©ããã¦ãããã¢ã¸ã¥ã¼ã«ç¸æã«class_evalã¨æ¸ãããã¯ã©ã¹ç¸æã«module_evalã¨æ¸ãããããã®ãæ°æã¡æªã人ã¯ä½¿ãåããã°ããã
module_evalãselfãå·®ãæ¿ããã
class Original CONST = :original $global = :original @@class = :original def create_proc @instance = :original local = :original return Proc.new{ p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local } end def modify @instance = :modified local = :modfied end CONST = :modified $global = :modified @@class = :modified end class Other CONST = :other @@class = :other $global = :other @instance = :other_class def Other.call(str, proc_by_method) local = :other @instance = :other module_eval(str) puts module_eval(&proc_by_method) end end orig = Original.new proc_by_method = orig.create_proc orig.modify # ã¤ã³ã¹ã¿ã³ã¹å¤æ°ãå¤æ´ãã¦ãã¾ãã # é¢ä¿ãªãã®ãèªæã ããã©ãããã¼ã«ã«å¤æ°ãã Other.call <<'EOS', proc_by_method p caller p self p __FILE__ p __LINE__ p CONST p $global p @@class p @instance p local EOS
ãããå®è¡ããã次ã®ããã«ãªã£ãã
æååç | ãããã¯ç | |
---|---|---|
caller | ["module_eval2.rb:55"] | ["module_eval2.rb:46:in `call'", "module_eval2.rb:55"] |
self | Other | Other |
__FILE__ | "(eval)" | "module_eval.rb" |
__LINE__ | 4 | 14 |
CONST | :other | :modified |
$global | :other | :other |
@@class | :other | :modified |
@instance | :other | :other |
local | :other | :original |
instance_evalã¨å¤ãããªãã§ã¯ãªãããModuleã ã£ã¦Objectã®ãµãã¯ã©ã¹ã ããã«ãããããinstance_evalã¨ã¯å¥ã«module_evalãå®ç¾©ããæå³ã¯ã©ãã«ããã®ã ããããããklassã説æããã¨ããæ¥ãã
äºå
ã¡ãã£ã¨é·ããªããããã®ã§ãããã§ä¸åãã¹ãããã次åã¯klassãæ¢ã£ã¦ã次åããã¯å¼ã³åºãå¯è½ãªãã¸ã§ã¯ããç¸äºå¤æãéãã¦å¼ãã£ã¦ã¿ãã
*1:å³å¯ã«ã¯ãã¹ã¼ãã¼ã¯ã©ã¹ãããµãã¯ã©ã¹ã«ã¯ç§»ãã