我现在正在学习Ruby。在过去几年中使用Javascript,我熟悉While循环。但直到循环?我环顾四周,却找不到一个比另一个好的原因。
Ruby有“until”,它被描述为另一种表达问题的方式。我看到它的方式,“while”迭代直到false,“until”迭代直到true。
我确信我编写的大多数程序都不需要重构速度。但是,我有时想深入了解一些细节。
两个循环之间是否存在速度差异?为什么Ruby中有“until”语法?为什么不坚持“while?”
答案 0 :(得分:5)
while
和until
之间没有速度差异,因为它们互为镜像。
我们会将while
循环与until
循环进行比较:
n = 0
puts n += 1 while n != 3
n = 0
puts n += 1 until n == 3
这些都会打印1到3。
这是来自Ruby VM的两个反汇编的人类可读指令序列之间的区别:
@@ -13,7 +13,7 @@
0021 pop
0022 getlocal_OP__WC__0 2
0024 putobject 3
-0026 opt_neq <callinfo!mid:!=, argc:1, ARGS_SIMPLE>, <callcache>, <callinfo!mid:==, argc:1, ARGS_SIMPLE>, <callcache>
-0031 branchif 8
-0033 putnil
-0034 leave
+0026 opt_eq <callinfo!mid:==, argc:1, ARGS_SIMPLE>, <callcache>
+0029 branchunless 8
+0031 putnil
+0032 leave
while
循环使用branchif
进行跳转,而until
循环使用branchunless
。因此,这些循环只是在进行比较时有所不同,您可以通过查看branchif
和branchunless
defined的方式来看到:
DEFINE_INSN
branchif
(OFFSET dst)
(VALUE val)
()
{
if (RTEST(val)) {
RUBY_VM_CHECK_INTS(th);
JUMP(dst);
}
}
DEFINE_INSN
branchunless
(OFFSET dst)
(VALUE val)
()
{
if (!RTEST(val)) {
RUBY_VM_CHECK_INTS(th);
JUMP(dst);
}
}
while
和until
之间的效果几乎相同。用法应由可读性决定。
答案 1 :(得分:3)
除了速度差异之外,它实际上都是关于可读性的,这是Ruby引以为豪的。
让我们假装我们正在喝酒 - 您认为哪种饮料更好?
A) pour_drink until glass.full?
B) pour_drink while !glass.full?
答案 2 :(得分:3)
选择比较运算符会比选择while
或until
Benchmark.bmbm do |bm|
bm.report('while') do
n = 0
n += 1 while n != 10_000_000
end
bm.report('until') do
n = 0
n += 1 until n == 10_000_000
end
end
user system total real
while 0.250000 0.000000 0.250000 ( 0.247949)
until 0.220000 0.000000 0.220000 ( 0.222049)
while n != 10_000_000
与until n == 10_000_000
相比,until
似乎更快。
Benchmark.bmbm do |bm|
bm.report('while') do
n = 0
n += 1 while n < 10_000_000
end
bm.report('until') do
n = 0
n += 1 until n == 10_000_000
end
end
user system total real
while 0.210000 0.000000 0.210000 ( 0.207265)
until 0.220000 0.000000 0.220000 ( 0.223195)
将其更改为while n < 10_000_000
,现在while
似乎有优势。公平地说,我们应该给他们更加相同的while n < 10_000_000
与until n > 9_999_999
Benchmark.bmbm do |bm|
bm.report('while') do
n = 0
n += 1 while n < 10_000_000
end
bm.report('until') do
n = 0
n += 1 until n > 9_999_999
end
end
user system total real
while 0.200000 0.000000 0.200000 ( 0.208428)
until 0.200000 0.000000 0.200000 ( 0.206218)
现在他们几乎完全相同。因此,请遵循Ruby的主导,并通过类似英语句子的代码获得满意度。但请确保使用<
或>
来获得额外的.0000000001秒的提升。