From: Ts on

The following script doesn't work...
Do you have any idea of what is wrong?
Is it a ruby bug? (ruby version: ruby 1.9.1p243 (2009-07-16 revision
24175) [i386-darwin9])

require 'time'

Time.parse("1999-10-31 16:46:50") # this works

class String
alias_method :old_sub!, :sub!
def sub!(*args, &block)
old_sub!(*args, &block)
end
end

Time.parse("1999-10-31 16:46:50") # this crashes

# =>
#
# ArgumentError: argument out of range
# from /opt/local/lib/ruby1.9/1.9.1/time.rb:202:in `local'
# from /opt/local/lib/ruby1.9/1.9.1/time.rb:202:in `make_time'
# from /opt/local/lib/ruby1.9/1.9.1/time.rb:261:in `parse'
# from (irb):10
# from /opt/local/bin/irb1.9:12:in `<main>'
--
Posted via http://www.ruby-forum.com/.

From: Brian Candler on
Thomas Sevestre wrote:
>
> The following script doesn't work...
> Do you have any idea of what is wrong?

There are loads of sub! calls in date/format.rb, but I have no idea why
delegating sub! in this way would break it.

I note that the same error occurs in 1.8.6 too:
ArgumentError: argument out of range
from /usr/lib/ruby/1.8/time.rb:184:in `local'
from /usr/lib/ruby/1.8/time.rb:184:in `make_time'
from /usr/lib/ruby/1.8/time.rb:243:in `parse'
from (irb):19

I copied time.rb to my local directory and modified it to puts the
arguments to local. I see that it is calling

Time.local(1999, 10, 31, 16, 46, 50, 0)

before the sub! change, but

Time.local(2009,0,1,0,0,0,0)

after it. Most bizarre.
--
Posted via http://www.ruby-forum.com/.

From: David A. Black on
Hi --

On Mon, 2 Nov 2009, Brian Candler wrote:

> Thomas Sevestre wrote:
>>
>> The following script doesn't work...
>> Do you have any idea of what is wrong?
>
> There are loads of sub! calls in date/format.rb, but I have no idea why
> delegating sub! in this way would break it.
>
> I note that the same error occurs in 1.8.6 too:
> ArgumentError: argument out of range
> from /usr/lib/ruby/1.8/time.rb:184:in `local'
> from /usr/lib/ruby/1.8/time.rb:184:in `make_time'
> from /usr/lib/ruby/1.8/time.rb:243:in `parse'
> from (irb):19
>
> I copied time.rb to my local directory and modified it to puts the
> arguments to local. I see that it is calling
>
> Time.local(1999, 10, 31, 16, 46, 50, 0)
>
> before the sub! change, but
>
> Time.local(2009,0,1,0,0,0,0)
>
> after it. Most bizarre.

I believe it's about the $1, $2... variables:

"abc".sub!(/(.)/, "z")
p $1 # nil
"abc".old_sub!(/(.)/, "z")
p $1 # "a"

When sub! calls old_sub!, the $n variables inside sub! are not set,
but the ones in old_sub! are. When the date parser hits _parse_iso (or
whichever of that family of methods it hits), there are calls to sub!
followed by usage of the $n variables, which are actually not set
because they're two methods removed.

A more generic example:

def y(str)
/(.)/.match(str)
p $1
end

def x(str)
y(str)
p $1
end

x("abc")

=> "a"
nil


David

--
The Ruby training with D. Black, G. Brown, J.McAnally
Compleat Jan 22-23, 2010, Tampa, FL
Rubyist http://www.thecompleatrubyist.com

David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)

From: Brian Candler on
> A more generic example:

So the $~ variables are both thread-local *and* scoped to the enclosing
method? That's definitely new to me. Thanks for the explanation.
--
Posted via http://www.ruby-forum.com/.

From: Thomas Sevestre on
Interesting! I wasn't aware of that.

Is there any way to make it work?

It is feasible in your generic example:

def y(str, b)
eval "/(.)/.match(str)", b
p $1
end

def x(str)
y(str, binding)
p $1
end

x("abc")

# =>
#
# nil
# "a"

But in my case, I need to find the caller's binding :

class String
alias_method :old_sub!, :sub!
def sub!(*args, &block)
eval "old_sub!(*args, &block)", caller_binding
end
end

But I havn't been able to retrieve it :( Do you have any idea?

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