我正在研究 Ruby 上的数组,这时我遇到了一种创建数组的方法(可能还有更多)。
arr1 = %w(first second third) # => ["first", "second", "third"]
我想知道,既然 Ruby 自己的方法减少了这么多样板,它们实际上可能很慢。但是考虑到 Ruby 是用 C 编写的,它对速度/性能有相当大的影响吗? (在有很多这样语句的程序中)
最佳答案
正如@theTinMan 在评论中提到的,您必须理解语言(语法)和逻辑(语义)之间的区别。例如,假设有人要求您编写一个程序来打印数字 1,000。你可能会这样写:
puts 1000
但是你也可以这样写:
放 1_000
输入 0b1111101000
放 01750
这些都是一样的。不是“相同”,因为它们产生相同的结果,而是“相同”,因为 Ruby 以完全相同的方式解析和执行它们。它们的语法不同,但语义相同。
对于 Ruby 的不同数组语法(及其等效的字符串语法、Regexp 文字等)也是如此。您可以使用 Ruby 的 --dump insns
(转储指令序列)选项自行测试:
$ ruby --dump insns -e 'arr = ["a", "b"]'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] arr
0000 trace 1 ( 1)
0002 putstring "a"
0004 putstring "b"
0006 newarray 2
0008 dup
0009 setlocal_OP__WC__0 2
0011 leave
$ ruby --dump insns -e 'arr = %w(a b)'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] arr
0000 trace 1 ( 1)
0002 putstring "a"
0004 putstring "b"
0006 newarray 2
0008 dup
0009 setlocal_OP__WC__0 2
0011 leave
完全相同。当然,最重要的指令是 0002–0006:
0002 putstring "a"
0004 putstring "b"
0006 newarray 2
这些说明(或多或少)说:
- (0002) 将字符串
"a"
压入栈顶。 - (0004) 将字符串
"b"
压入栈顶。 - (0006) 从堆栈中弹出顶部的两个值,从中创建一个数组并将其压入堆栈。
这些是 MRI VM 在这两种情况下将执行的实际指令。 Ruby 永远不知道您使用的是 %w( ... )
而不是 [ ... ]
并且它不需要执行额外的代码。
关于ruby - Ruby 自带方法的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37442812/