2014-02-05 28 views
2

按照docs,相信下面的Ruby 1.9.2的例子應該以同樣的方式像Ruby 1.9.3工作,但事實並非如此。給定一個文件test與內容hello可選參數使用Ruby 1.9.2

紅寶石1.9.3p484:

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

紅寶石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。爲什麼?我無法弄清楚這個改變是在哪裏進行的。

+0

FWIW,我不能重現這個(紅寶石1.9.3p286,I386-cygwin的/紅寶石1.9.3p125,I386-的mingw32) –

+0

@FrankSchmitt它有1.9.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' 
+0

方法簽名'讀(姓名,[長度[,偏移],open_args)'沒有缺省值,所以,爲了在'open_args'通過,以前的值必須先於它們。由於OP要從文件的開頭讀取,所以'0'可能可以接受。 –

+0

傳遞'nil'或0可能會工作,但我更感興趣的是* *爲什麼這是擺在首位的問題,以及* *爲什麼它顯然不是1.9.3。它是1.9.2中的錯誤嗎? – johnrl

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是:

diff

所以他們實際上是不同的。