Ruby 1.8和Ruby 1.9中`Array#to_s`的区别

3

可能是重复的问题:
Ruby 1.9 Array.to_s behaves differently?

我想知道在 Ruby 1.8.7 和 Ruby 1.9.3 之间有什么变化。下面列出了一个示例,在这两个版本中表现完全不同,但根据 Ruby 文档,似乎这些版本之间没有任何变化。

Ruby 1.8

number = '123-45-6789' 
# => "123-45-6789"
number.scan(/[0-9]/)
# => ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
number.scan(/[0-9]/).to_s
# => "123456789"

Ruby 1.9

number = '123-45-6789'
# => "123-45-6789" 
number.scan(/[0-9]/)
# => ["1", "2", "3", "4", "5", "6", "7", "8", "9"]    
number.scan(/[0-9]/).to_s
# => "[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]"

我并不是在寻找另一种做法,只是好奇两个版本之间发生了什么变化。


3
当一个新学习者没有和你得出相同的结论时,如果你用侮辱的方式对待这个好奇心的人,那么我们的社区就会受到伤害。记住:Matz 很友好,所以我们也要友好(MINASWAN)。 - Sean
@sawa 我对Ruby还很陌生,所以我来这里寻求帮助。感谢你费心给我回复,让我感到自己非常愚蠢。 - mpowmap
3个回答

5

以下是 Ruby 源代码的实际内容:

1.8.7 版本:

rb_ary_to_s(ary)
    VALUE ary;
{
    if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
    return rb_ary_join(ary, rb_output_fs);
}

换句话说,在1.8.7中,to_s 调用了 join 方法。
1.9.3版本:
rb_ary_inspect(VALUE ary)
{
    if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
    return rb_exec_recursive(inspect_ary, ary, 0);
}

VALUE
rb_ary_to_s(VALUE ary)
{
    return rb_ary_inspect(ary);
}

换句话说,在1.9.3版本中,to_s委托给了inspect
注意:将来如果您想知道两个版本之间的差异,可以尝试查看源代码。可以从这里轻松下载:https://github.com/ruby/ruby 当然,并非所有内容都容易在其中找到,但如果您搜索一下,通常可以找到很好的线索。在这种情况下,array.c有您要查找的内容。
然后,您可以通过发出git checkout ruby_1_8_7git checkout ruby_1_9_3来在不同版本之间切换。

啊!我能看出为什么1.8的实现在我的微基准测试中更快了。谢谢分享! - Igbanam
github的blame功能带我到了提交记录,那里的评论又带我去了讨论区,但这对我了解原因没有太大帮助。 - Martin Dorey

2
to_s方法已经改变,现在它的功能符合将对象转换为字符串的实际需求。
考虑1.8版本的实现...
1. 当你将to_s方法发送给数组对象时,它实际上执行的是array_object.join('').to_s。我认为这做得太多了。
2. 这个实现也误导了数组对象。主要使用to_s方法来配合inspect方法(如果我说错了,请纠正我,因为我凭记忆工作)。如果你查看这里to_s方法的输出,你无法确定对象是否属于ArrayString或者Fixnum类。
进入1.9版实现...
1.输出的结构明确显示了对象是一个数组。
话虽如此,我认为这是Ruby团队做出的用户体验设计决策......因为1.8版本中to_s的速度相当快!
请看下面的微基准测试...
OS_X_Terminal $> time ruby -e "(1..1000000).to_a.map(&:to_s).to_s"

| Ruby Version | average runtime |
|    1.9.3     |      1.678      |
|    1.9.2     |      1.817      |
|    1.8.7     |      1.106      |

这是我目前的全部内容。欢迎留言(:

0

看起来 Ruby 对 .to_s 的处理变得更加智能了。以前它很愚蠢,出于某种原因会将数组中的所有条目并排列出来。在 Ruby 1.9 中,它将数组直接转换为字符串。这是一种更加智能的处理 .to_s 的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接