Я читаю раздел "Метапрограммирование" в "Программирование Ruby 1.9", и мне трудно понять, что происходит внутри между class_eval/class_exec и instance_eval/instance_exec.
Итак, в первую очередь, я понимаю, что def добавляет метод в таблицу методов self (объект класса):
class A
puts self # => A
def foo; 42; end # added to the method table of self, so becomes an instance method
end
A.new.foo # => 42
И если мы используем class_eval, мы получим то же поведение:
A.class_eval do
puts self # => A
def bar; 42; end # same as above
end
A.new.bar # => 42
Но как-то в случае instance_eval все по-другому:
A.instance_eval do
puts self # => A
def baz; 42; end # added to the method table of an anonymous
# singleton class of self, so becomes a class method
end
puts A.baz # => 42
s = 'string'
s.instance_eval do ... end # same behavior, so now def creates an instance method
Итак, я понимаю функциональную разницу между class_eval и instance_eval.
Но контексты внутри блоков class_eval и instance_eval выглядят одинаково для меня - в частности, self указывает на один и тот же объект, а local_variables - то же самое. Итак, что происходит внутри блоков (внутренне), что делает def действовать иначе?
Есть ли какая-то документация, которую я мог бы прочитать? RDoc для instance_eval и class_eval не помогает. Глядя на источник, instance_eval, кажется, настроил объект одноэлементного класса, тогда как class_eval нет - но разве это отличие видимо вне кода C, на уровне Ruby?