Binding#eval issue

I have the following extensions to Binding:

class Binding

# Returns line number of the binding.
def __LINE__
  eval("__LINE__")
end

# Returns file name of the binding.
def __FILE__
  eval("__FILE__")
end

end

The work fine in 1.8.7 (or lower when you define Binding#eval), but
fails in 1.9 where it returns “(eval)” instead of the file name and
nothing at all for the line number.

Any idea on how to fix? Should this be considered a 1.9 bug?

Thomas S. wrote:

I have the following extensions to Binding:

class Binding

# Returns line number of the binding.
def __LINE__
  eval("__LINE__")
end

# Returns file name of the binding.
def __FILE__
  eval("__FILE__")
end

end

The work fine in 1.8.7

I tried this, and was surprised to find that 1.8.7 makes a special case
of eval inside an instance method of Binding:

$ irb --simple-prompt

RUBY_VERSION
=> “1.8.7”

RUBY_PATCHLEVEL
=> 174

class Binding; def LINE; eval “LINE”; end; end
=> nil

class Binding; def FILE; eval “FILE”; end; end
=> nil

binding.LINE
=> 6

binding.LINE
=> 7

binding.FILE
=> “(irb)”

binding.FILE
=> “(irb)”

This is particularly surprising given that instance_eval doesn’t show
this behaviour:

binding.instance_eval “LINE
=> 1

binding.instance_eval “LINE
=> 1

binding.instance_eval “FILE
=> “(eval)”

binding.instance_eval “FILE
=> “(eval)”

FILE is the filename where the source being executed is found. When
eval’ing from a string, the source is not in any particular file and so
I’d always expect “(eval)” to be returned, and LINE to be relative
to the start of the string, unless you pass file and/or line numbers as
extra args to eval.

In ruby 1.9.2 this works as I’d expect:

$ irb19 --simple-prompt

RUBY_REVISION
=> 24186

class Binding; def LINE; eval “LINE”; end; end
=> nil

class Binding; def FILE; eval “FILE”; end; end
=> nil

binding.LINE
=> 1

binding.LINE
=> 1

binding.FILE
=> “(eval)”

binding.FILE
=> “(eval)”

So I’d say that 1.8.7 is the anomoly.

On Feb 22, 11:46 am, Brian C. [email protected] wrote:

I tried this, and was surprised to find that 1.8.7 makes a special case
of eval inside an instance method of Binding:

Right. I thought that was idea because you want to know about the
binding, not the instance of Binding.

binding.LINE
binding.instance_eval “LINE
eval’ing from a string, the source is not in any particular file and so
class Binding; def FILE; eval “FILE”; end; end

So I’d say that 1.8.7 is the anomoly.

In that case there would be no way to define these manually. And I
would need to request that Binding support LINE and FILE in
core.

But I’m not so sure, because there has to be a way to access the
binding itself or what is the point? Perhaps Binding needs a special
method, ie. #binding_eval, which would eval as if in the binding.

On 2/22/2010 10:48 AM, Intransition wrote:

In that case there would be no way to define these manually. And I
would need to request that Binding support LINE and FILE in
core.

But I’m not so sure, because there has to be a way to access the
binding itself or what is the point? Perhaps Binding needs a special
method, ie. #binding_eval, which would eval as if in the binding.

You can just pass your binding to eval. See:
http://ruby-doc.org/core/classes/Kernel.html#M005922

On Feb 22, 12:54 pm, Walton H. [email protected] wrote:

But I’m not so sure, because there has to be a way to access the
binding itself or what is the point? Perhaps Binding needs a special
method, ie. #binding_eval, which would eval as if in the binding.

You can just pass your binding to eval. See:module Kernel - RDoc Documentation

That’s how the above works actually, Binding#eval is defined as:

class Binding
def eval(str)
Kernel.eval(str, self)
end
end