使用Ruby 1.9.2在`File.read`中的可选参数

时间:2014-02-05 11:14:09

标签: ruby file ruby-1.9.2

根据docs,我相信下面的例子与Ruby 1.9.2应该像Ruby 1.9.3一样工作,但事实并非如此。给定文件test,其内容为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

Ruby 1.9.2和1.9.3似乎在处理File.read的可选参数方面有所不同。为什么?我无法弄清楚这个改变是在哪里说的。

2 个答案:

答案 0 :(得分:1)

如果你指定长度,Ruby 1.9.2似乎也期望偏移(在相关新闻中,我也可以在1.9.2p320上重现这一点,但不能在1.9.3p484上重现)。从文档和C代码中我不清楚为什么在1.9.2上需要这样做但这不应该是一个太大的问题。

你可以使用nil传递偏移量,它可以在1.9.3和1.9.2上正常工作。

File.read "test", 4, nil, :mode => 'rb'

答案 1 :(得分:0)

补充Holger Just的答案。

源代码实际上似乎有所不同。

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);
}

差异是:

diff

所以他们实际上是不同的。