Reputation: 583
According to the docs, I believe the example below with Ruby 1.9.2 should work in the same way as Ruby 1.9.3, but it doesn't. Given a file test
with the contents hello
:
Ruby 1.9.3p484:
File.read "test", 4, :mode => 'rb'
# => "HELL"
Ruby 1.9.2p320
File.read "test", 4, :mode => 'rb'
# => TypeError: can't convert Hash into Integer
It seems like Ruby 1.9.2 and 1.9.3 differ in their way of handling optional args to File.read
. Why? I cannot figure out where it's stated that this change was made.
Upvotes: 2
Views: 121
Reputation: 168189
Complementing Holger Just's answer.
The source code actually seems to be different.
Ruby 1.9.2
static VALUE
rb_io_s_read(int argc, VALUE *argv, VALUE io)
{
VALUE offset;
struct foreach_arg arg;
rb_scan_args(argc, argv, "13", NULL, NULL, &offset, NULL);
open_key_args(argc, argv, &arg);
if (NIL_P(arg.io)) return Qnil;
if (!NIL_P(offset)) {
struct seek_arg sarg;
int state = 0;
sarg.io = arg.io;
sarg.offset = offset;
sarg.mode = SEEK_SET;
rb_protect(seek_before_access, (VALUE)&sarg, &state);
if (state) {
rb_io_close(arg.io);
rb_jump_tag(state);
}
if (arg.argc == 2) arg.argc = 1;
}
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
Ruby 1.9.3
static VALUE
rb_io_s_read(int argc, VALUE *argv, VALUE io)
{
VALUE opt, offset;
struct foreach_arg arg;
argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
open_key_args(argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
if (!NIL_P(offset)) {
struct seek_arg sarg;
int state = 0;
sarg.io = arg.io;
sarg.offset = offset;
sarg.mode = SEEK_SET;
rb_protect(seek_before_access, (VALUE)&sarg, &state);
if (state) {
rb_io_close(arg.io);
rb_jump_tag(state);
}
if (arg.argc == 2) arg.argc = 1;
}
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
And the diff is:
So they are actually different.
Upvotes: 0
Reputation: 55833
It seems like Ruby 1.9.2 also expects the offset if you specify the length (in related news, I can also reproduce this on 1.9.2p320 but not on 1.9.3p484). It is not clear to me from the documentation and the C code why this would be required on 1.9.2 but it shouldn't be too big a problem here.
You can just use pass the offset as nil
and it will work fine on 1.9.3 and 1.9.2.
File.read "test", 4, nil, :mode => 'rb'
Upvotes: 1