我在Ruby中有这样的方法:
def guess
random_guess = rand(4)
if random_guess == 0
guess
end
puts random_guess
end
guess
正如你所看到的,它意味着生成一个介于0和4之间的随机数,然后在数字为0时重复出现。这个想法是让方法永远不会打印出来。但是,它似乎不是出于某种奇怪的原因这样做。例如,以下是random_guess
获取值0时IRB中的示例:
2.2.0 :001 > def guess
2.2.0 :002?> random_guess = rand(4)
2.2.0 :003?> if random_guess == 0
2.2.0 :004?> guess
2.2.0 :005?> end
2.2.0 :006?>
2.2.0 :007 > puts random_guess
2.2.0 :008?> end
=> :guess
2.2.0 :009 > guess
2
0
0
0
0
=> nil
2.2.0 :010 >
当它没有得到值0时,程序运行正常,只是打印出该范围内的任何其他随机数:
2.2.0 :010 > guess
1
=> nil
2.2.0 :011 >
我想知道的是,为什么程序在random_guess
为0时发生的递归行为如此奇怪。看起来它是反复发生的,但似乎并没有在正确的条件下停止,即当random_guess
不为0时。为什么会发生这种情况?
答案 0 :(得分:2)
当random_guess
为0
时,guess
会递归调用自身,这是正常的。您看到的输出是因为{/ 1}}在递归后执行。所以当你看到输出时,例如:
puts random_guess
3
0
被称为:guess
获取random_guess
,因此请致电0
。guess
内,guess
获取random_guess
,
当前3
,即random_guess
。退出内部 3
guess
的值放在 outter random_guess
中,这是
guess
,然后退出。答案 1 :(得分:0)
这正是你告诉它的。如果得到非零值,则不输入if
- 子句,因此立即打印非零并完成。
但是,如果生成的第一个值为零,则输入递归并重复该过程,直到产生非零值。只有这样你才能绕过if
来遇到print语句并从递归中返回。由于只有在零时才调用递归,现在打印该零并返回。
净结果,输出将是一个非零值,然后是所有出现的零,当你弹出堆栈时,它们的顺序相反。
答案 2 :(得分:0)
因为recursive
。保持每个剩余指令的堆栈。
如果0出现,它将在堆栈中添加puts random_guess
行。在完成递归guess
调用后,它会弹出剩余的指令。
所以它打印0直到guess
的许多递归调用。
答案 3 :(得分:0)
# closer to your original design
# fyi, returns values 1 - 3
def guess
random_guess = 0
while random_guess == 0
random_guess = get_random_guess(4)
end
random_guess
end
def get_random_guess(max_guess)
rand(4)
end
# test guess 100 times
(1..100).each { puts "guess=#{guess}" }
# faster, note the use of rand without a max parameter.
# in this case, rand returns a float between 0 and 1
# this return values between min_guess and max_guess
def faster_guess(min_guess, max_guess)
(rand() * (max_guess + 1 - min_guess)).to_i + min_guess
end
# test faster_guess 100 times
# will return values between 1 - 4
(1..100).each { puts "faster_guess=#{faster_guess(1,4)}" }
答案 4 :(得分:0)
因为您将puts
语句放在方法中,所以它会在每次调用时打印出随机猜测的值,无论是0
还是0
。递归调用自身的方法只会暂时中断该点的控制流,直到它向上移回堆栈。
您要做的是让方法返回不是def guess
random_guess = rand(4)
(random_guess > 0) ? random_guess : guess
end
puts guess
# 1 (never 0)
的第一个值。例如:
random_guess
在此修改方法中,如果条件大于0
,则条件将返回{{1}}。如果没有,它将递归调用自身,直到满足条件。
请注意,这种递归理论上的使用创建了无限递归的可能性,虽然这在实践中永远不会发生,但该方法的执行时间将是随机的。