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 Sawyer 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.

···

--
Posted via http://www.ruby-forum.com/\.

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.

$ 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.

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 Feb 22, 11:46 am, Brian Candler <b.cand...@pobox.com> wrote:

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

···

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.

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

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

···

On Feb 22, 12:54 pm, Walton Hoops <wal...@vyper.hopto.org> 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