Feature #6710

new special binding specifier :isolated

Added by Koichi Sasada almost 2 years ago. Updated over 1 year ago.

[ruby-core:46262]
Status:Assigned
Priority:Normal
Assignee:Koichi Sasada
Category:core
Target version:next minor

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 asrequire' and 'load'.
It is a bit different from `TOPLEVEL_BINDING'.

= Background

We have TOPLEVELBINDING 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', TOPLEVELBINDING)
eval('b=2', TOPLEVEL
BINDING)
eval('c=3', TOPLEVELBINDING)
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 tomain' 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 asrequire' 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 ::ISOLATEDBINDING as a :isolated, then we can use it as `eval(src, ISOLATEDBINDING)', similar manner with TOPLEVEL_BINDING.

= Acknowledgment

Usa-san proposed the name isolated'. My first idea of this name isempty'.

=end

History

#1 Updated by Koichi Sasada almost 2 years ago

  • Description updated (diff)
  • Category set to core
  • Assignee set to Yukihiro Matsumoto
  • Target version set to 2.0.0

#2 Updated by Joshua Ballanco almost 2 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, ISOLATEDBINDING would be something like
b = Binding.new(TOPLEVEL
BINDING) # New binding "inherits" from Top Level (but not same as class inheritance)
b.livelocals = false # This binding will not propagate locals to its "parent" binding (TOPLEVELBINDING, 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

#3 Updated by Koichi Sasada almost 2 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 to Binding.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, ISOLATEDBINDING would be something like
b = Binding.new(TOPLEVEL
BINDING) # New binding "inherits" from Top Level (but not same as class inheritance)
b.livelocals = false # This binding will not propagate locals to its "parent" binding (TOPLEVELBINDING, 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?

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

#4 Updated by Yusuke Endoh almost 2 years ago

  • Status changed from Open to Assigned

#5 Updated by Yukihiro Matsumoto over 1 year ago

  • Assignee changed from Yukihiro Matsumoto to 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.

#6 Updated by Koichi Sasada over 1 year 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.

#7 Updated by Yusuke Endoh over 1 year ago

  • Target version changed from 2.0.0 to next minor

Also available in: Atom PDF