look at me
from /usr/local/bin/irb:12:in `’
behaves differently inside a method definition.
It’s not that eval behaves differently inside a method definition. It’s
just that it takes into account the scope in which it was called.
When inside the String class, or any other class for that matter, if you
create another class, you can’t call it from outside the parent class
without referring to the parent. So for example:
class String
class Pumpkin
def pie
puts ‘yum’
end
end
end
Pumpkin.new #=> NameError: uninitialized constant Pumpkin
String::Pumpkin.new #=> #Pumpkin:0x109896c
The parent class effectively acts as a namespace for the subclass. BTW,
I really don’t think I should call it a “subclass”, as that seems to
imply inheritence - none of that here. Maybe someone else can tell us
the proper name for this structure/pattern.
So you probably understand the issue by now, eval within the String
class (whether or not inside a method definition) creates a “subclass”
of sorts, and hence you can’t call it directly outside. If you tried to
call “String::Pumpkin.new” instead after using your “irb” method, it
would have worked (try it out). Alternately, you could have done it this
way:
class String
def irb
eval self
end
end
“class ::Pumpkin;def pie;puts ‘yum’;end;end”.irb
Pumpkin.new.pie
The parent class effectively acts as a namespace for the subclass. BTW, I really don’t think I should call it a “subclass”, as that seems to imply inheritence - none of that here. Maybe someone else can tell us the proper name for this structure/pattern.
I understand–how about nested class or encapsulated class.
Hope that helps.
Ehsan
Ehsan, nice explanation!
Hmmm. That means that you could make a binding to main
SPECIAL_BINDING = binding
and add that to the eval argument to get it back to the main scope
where eval seems to work on anything:
class String
def irb
eval(self, SPECIAL_BINDING)
end
end