首选%w(...)到文字数组?

Joh*_*ing 29 ruby

在RubyMine中输入一个简单的文字字符串数组时:

cols =
[
  "Col1",
  "Col2"
]
Run Code Online (Sandbox Code Playgroud)

RubyMine抱怨我更喜欢使用%w文字数组:

cols = %w(Col1 Col2)
Run Code Online (Sandbox Code Playgroud)

它提供了一个Ruby样式指南(这里)的链接,该指南说:

当需要字符串数组时,首选%w到文字数组语法.

# bad
STATES = ['draft', 'open', 'closed']

# good
STATES = %w(draft open closed)
Run Code Online (Sandbox Code Playgroud)

我可以看到如何%w提供可能更简洁的代码.除了简洁之外,有没有理由更喜欢一种方法而不是另一种方法?

the*_*Man 30

瞧!,一个基准:

require 'benchmark'

n = 1_000_000
Benchmark.bm(11) do |b|
  b.report('%w') { n.times { %w[a b c d e f g h i j k l m n o p q r s t u v w x y z] } }
  b.report('explicit') { n.times { ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] } }
  b.report('numerics') { n.times { [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] } }
end

                  user     system      total        real
%w            2.590000   0.000000   2.590000 (  2.591225)
explicit      2.590000   0.000000   2.590000 (  2.584781)
numerics      0.300000   0.000000   0.300000 (  0.309161)

                  user     system      total        real
%w            2.590000   0.000000   2.590000 (  2.591516)
explicit      2.590000   0.000000   2.590000 (  2.584155)
numerics      0.300000   0.000000   0.300000 (  0.308896)

                  user     system      total        real
%w            2.590000   0.000000   2.590000 (  2.592848)
explicit      2.590000   0.000000   2.590000 (  2.585558)
numerics      0.300000   0.000000   0.300000 (  0.308570)
Run Code Online (Sandbox Code Playgroud)

我添加了"数字"阵列测试,因为我怀疑%w由于测试字符串而比使用显式字符串更快.%w不需要这样做,因为它假设一切都是字符串.在运行三次之后,只要处理字符串就可以了.数字规则,字符串流口水,以及所有这些.


之前的基准测试是在我的系统上使用Ruby 1.9.3-p286运行的.我在家里使用我的旧MacBook Pro再次测试,使用Ruby 1.8.7-p358,因此由于托管硬件的差异以及运行较旧的Ruby,以下数字较慢:

                user     system      total        real
%w           3.070000   0.000000   3.070000 (  3.080983)
explicit     3.100000   0.000000   3.100000 (  3.093083)
numerics     0.950000   0.040000   0.990000 (  0.990535)

                user     system      total        real
%w           3.080000   0.010000   3.090000 (  3.076787)
explicit     3.090000   0.000000   3.090000 (  3.089246)
numerics     0.950000   0.030000   0.980000 (  0.989579)

                user     system      total        real
%w           3.080000   0.000000   3.080000 (  3.073877)
explicit     3.090000   0.000000   3.090000 (  3.091576)
numerics     0.950000   0.030000   0.980000 (  0.989132)
Run Code Online (Sandbox Code Playgroud)

在1.8.7,%w持续一点点快,这可能引起了速度谣言.

  • 两者都是*完全相同的东西*.如果*甚至*是*任何性能差异,它可能*仅*在*解析*期间.*不能*可能是任何*运行时*性能差异,因为两者都是*完全相同的东西*.由于整个文件在*之前被解析*基准甚至开始,整个基准测试都没有意义.您需要使用`eval`或`load`或类似的东西来延迟解析,直到基准测试开始之后. (6认同)
  • @dbenhur:这里不需要智能编译器.在JRuby和Rubinius上,两段代码都被解析为*完全相同的*AST,*之前*它们甚至可以正确地命中编译器.在YARV上,AST略微不同*,但生成的字节码是相同的:`putstring'a'; putstring'b'; putstring'c'; newarray 3;`.请注意,YARV编译器非常不是*SSC,相反:它是一个非常愚蠢的编译器. (3认同)
  • @JörgWMittag你断言它们是完全相同的东西;但这仅适用于_足够智能的编译器_。%w{...} 始终是文字数组,而 `[...]` 可以是文字数组或表达式数组或混合。编译器可以在解析后分析数组,以了解它是一个文字数组,因此在代码生成时完全构造它,但这并不是一种完全微不足道的优化,应该始终假设您无需文档、测试或代码检查即可获得。 (2认同)
  • @JörgWMittag的ruby实现非常简单.我甚至不确定mri是否进行简单的编译时间常量表达式评估.我的观点是,人们不能假设%w {}和[literals]都会编译成相同的代码和数据而不进行实际调查.你反复断言它们确实没有通过发布指向编译器代码的指针来表明它,或者向我们展示一个示例AST /字节码输出来证明它们的等价性.贬低尝试通过基准测试而不展示你的断言只是令人讨厌. (2认同)