Feature #6710
closednew special binding specifier :isolated
Description
=begin
= Abstract
New special binding specifier :isolated for the 2nd argument of eval() method.
eval(src, :isolated) evaluates src' program on the same environment as
require' and 'load'.
It is a bit different from `TOPLEVEL_BINDING'.
= Background
We have TOPLEVEL_BINDING to evaluate source code on the main environment (self is `main', and so on).
However, TOPLEVEL_BINDING contains local variables which are evaluated in toplevel.
For example:
x = 10
eval('a=1', TOPLEVEL_BINDING)
eval('b=2', TOPLEVEL_BINDING)
eval('c=3', TOPLEVEL_BINDING)
eval('p (a+b+c) * x', TOPLEVEL_BINDING) #=> 60
To simulate "require()" or "load()" method, the eval() method with TOPLEVEL_BINDING is not enough (require() and load() methods don't evaluate scripts within main' environment. Similar to
main' environment (self == main), but local variables aren't taken over).
BTW, eval() receive special binding specifier `nil' (which means current binding).
= Proposal
Introduce the new special binding specifier :isolated for the 2nd argument of eval() method.
eval(src, :isolated) evaluates src' program on the new binding, which is same environment as
require' and 'load'.
== Usecase
Users can define toplevel methods, modules, classes on the any places.
def m
# define toplevel method foo()
eval('def foo(); end', :isolated)
# define ::Bar class
eval('class Bar; end', :isolated)
end
Users can make your own alternative require() method.
def my_require(feature)
... # set src from feature
eval(src, :isolated)
...
end
== Consideration
- :isolated is good name or not?
I'm not sure the `isolated' is good name or not.
- ISOLATED_BINDING = :isolated
If make default constants ::ISOLATED_BINDING as a :isolated, then we can use it as `eval(src, ISOLATED_BINDING)', similar manner with TOPLEVEL_BINDING.
= Acknowledgment
Usa-san proposed the name isolated'. My first idea of this name is
empty'.
=end
Updated by ko1 (Koichi Sasada) over 12 years ago
- Description updated (diff)
- Category set to core
- Assignee set to matz (Yukihiro Matsumoto)
- Target version set to 2.0.0
Updated by jballanc (Joshua Ballanco) over 12 years ago
=begin
I like this idea, but I have one question: why make this a special argument to eval
and not to Binding.new
? I've wanted Binding
to become better specified and more refined for some time now, and I think this would be a good step in the right direction. I think at some point it would be good to think about all of the things that can happen in a binding (e.g. specify locals, shadow locals, function defs, shadow defs, new classes, reopening classes, etc.), and give an API to tell bindings what they can and cannot do.
So, in this case, ISOLATED_BINDING would be something like
b = Binding.new(TOPLEVEL_BINDING) # New binding "inherits" from Top Level (but not same as class inheritance)
b.live_locals = false # This binding will not propagate locals to its "parent" binding (TOPLEVEL_BINDING, in this case)
eval('def foo; end; a = 10', b) # method foo is now available, but local "a" is not
This, obviously, requires a lot more thought and work, but for now we could maybe at least have Binding.new(isolated: true)
as shorthand for the case described above?
=end
Updated by ko1 (Koichi Sasada) over 12 years ago
Hi,
(2012/07/09 23:19), jballanc (Joshua Ballanco) wrote:
I like this idea, but I have one question: why make this a special argument to
eval
and not toBinding.new
?
Just a performance. My proposal doesn't make any binding object.
It is similar that `nil' specifier (means current binding).
I've wanted
Binding
to become better specified and more refined for some time now, and I think this would be a good step in the right direction. I think at some point it would be good to think about all of the things that can happen in a binding (e.g. specify locals, shadow locals, function defs, shadow defs, new classes, reopening classes, etc.), and give an API to tell bindings what they can and cannot do.So, in this case, ISOLATED_BINDING would be something like
b = Binding.new(TOPLEVEL_BINDING) # New binding "inherits" from Top Level (but not same as class inheritance)
b.live_locals = false # This binding will not propagate locals to its "parent" binding (TOPLEVEL_BINDING, in this case)
eval('def foo; end; a = 10', b) # method foo is now available, but local "a" is notThis, obviously, requires a lot more thought and work, but for now we could maybe at least have
Binding.new(isolated: true)
as shorthand for the case described above?
This is another feature. Make another ticket for it if you want.
I agree that we need more and more thought to introduce your proposal.
--
// SASADA Koichi at atdot dot net
Updated by mame (Yusuke Endoh) over 12 years ago
- Status changed from Open to Assigned
Updated by matz (Yukihiro Matsumoto) about 12 years ago
- Assignee changed from matz (Yukihiro Matsumoto) to ko1 (Koichi Sasada)
Ko1, explain why you need modify eval, where we can create new isolated binding.
I don't think small performance improvement is a good excuse.
Matz.
Updated by ko1 (Koichi Sasada) about 12 years ago
Yes, (small) performance issue.
Okay, let's discuss how to make such binding. I think we have several choice.
- Binding.new
- Binding.new(:isolated)
Or do we need to discuss jballanc's proposal in another ticket and reject this ticket? I'm okay this way.
Updated by mame (Yusuke Endoh) almost 12 years ago
- Target version changed from 2.0.0 to 2.6
Updated by ko1 (Koichi Sasada) almost 8 years ago
- Status changed from Assigned to Rejected