以下方法的输出为[6,4,2,0,0,2,4,6]
。
我理解n = 1处阵列= [6,4,2,0,0]的所有内容,在第4行添加了数组[4] = 0。 3.但是我完全难以理解为什么即使在执行第3行之后该方法仍继续执行,然后将[6,4,2,0,0]返回到原始方法调用。更令人烦恼的是,n重置为n = 1并且递增到n = 2并且n = 3 ... n = 3是方法调用中传递的起始参数值。
另外,我在理解各种可能性的递归方面遇到了重大问题。这个问题的答案和关于傻瓜的递归的建议'非常感谢!
def append(array, n)
return array if n < 0 #base case, how we end this thing
array << n*2 #Line No. 1
append(array, n - 1) #Line No. 2
array << n*2 #Line No. 3
end
append( [], 3)
#output [6,4,2,0,0,2,4,6]
答案 0 :(得分:2)
这里的执行顺序并不神秘,你的计数器也不会增加。要了解会发生什么,让我们逐行浏览代码。我会append([], 2)
让它更快。
# you call append([], 2)
return array if n < 0
# n >= 0 so we continue
array << n*2
# array is now [4]
append(array, n - 1)
# you call append(array, 1) which will mutate array,
# lets call x what will be appended to it
# array is now [4, x]
array << n*2
# array is now [4, x, 4]
# you get [4, x, 4] as a returned value from the append method
# because after the first line there is no return statement,
# so the return value of the last line is returned
# let's now see what x, that is append(array, 1) is
return array if n < 0
# n >= 0 so we continue
array << n*2
# array is now [4, 2] because at that time, array is [4]
append(array, n - 1)
# you call append(array, 0) which will mutate array,
# lets call y what will be appended to it
# array is now [4, 2, y]
array << n*2
# array is now [4, 2, y, 2]
# this is what you return to the first method invocation
# so we can replace [4, x, 4] with [4, 2, y, 2, 4]
# let's now see what y, that is append(array, 0) is
return array if n < 0
# n >= 0 so we continue
array << n*2
# array is now [4, 2, 0] because at that time, array is [4, 2]
append(array, n - 1)
# you call append(array, -1) which will mutate array,
# lets call z what will be appended to it
# array is now [4, 2, 0, z]
array << n*2
# array is now [4, 2, 0, z, 0]
# this is what you return to the second method invocation
# so we can replace [4, 2, y, 2, 4] with [4, 2, 0, z, 0, 2, 4]
# now in the last invocation, z is nothing because -1 < 0,
# so nothing is appended to the array
# the first method invocation returns [4, 2, 0, 0, 2, 4]
return
语句仅从其立即方法调用返回。方法是递归的这一事实并没有改变这一点。它不会以某种方式找到自己的顶级调用并从中返回。
如果我在处理递归时可以给你一个建议,那就是不要改变你的论点。使用纯函数更容易和直观,特别是在这种情况下。这就是你的append
方法没有突变的样子:
def append n
return n < 0 ? [] : [n * 2, append(n - 1), n * 2].flatten
end
你可以这样称呼它:
array = append(3)
# [6, 4, 2, 0, 0, 2, 4, 6]
通过这种方式,您的数组不会发生变异,您可以更清楚地了解该方法返回的内容。
如果你发现它不清楚,可以这样形象化
# append(3)
[6,
# append(2)
[4,
# append(1)
[2,
# append(0)
[0,
# append(-1)
[]
, 0].flatten
, 2].flatten
, 4].flatten
, 6].flatten
答案 1 :(得分:1)
该方法被多次调用。谈论&#34;该方法如何继续执行&#34;已经证明你没有错误地考虑这个问题。
该方法的每次调用都完全独立于每个其他调用,并且每次调用都有n
的唯一副本及其自己的值。该方法被调用四次,并且这四次调用中的每一次都将两个项目推送到数组中,总共产生八个项目。
承担正在发生的事情的关键是每个方法调用将数字推送到数组上,然后调用自身,然后将另一个数字推送到数组上。两者&#34; 6&#34; entires由相同的方法调用推送,并且它们包装所有其他条目,因为在 请考虑以下事项: 这不是递归的,但它的行为方式类似。此代码的输出是: 这与您希望看到的相反: 每个功能输出一个&#34; start&#34; line,调用它的下一个函数,然后当嵌套调用返回时,它输出&#34; end&#34;线。这正是您的递归函数的行为方式。在嵌套调用返回后,每次调用都会继续执行。 array << n*2
为6的方法中,在两个n
调用之间发生 < / p>
def method_a
puts "A start"
method_b
puts "A end"
end
def method_b
puts " B start"
method_c
puts " B end"
end
def method_c
puts " C start"
puts " !!!"
puts " C end"
end
method_a
A start
B start
C start
!!!
C end
B end
A end
A start
B start
C start
!!!
n
的本地值未更改,并且第二次被推送到数组上。
答案 2 :(得分:1)
我认为您认为return
会结束所有事情,但事实并非如此。
以下是正在发生的事情,一步一步:
append(array = [], n = 3) # initial call
array << 6 #Line No. 1
append(array = [6], n = 2) #Line No. 2
array << 4 #Line No. 1
append(array = [6,4], n = 1) #Line No. 2
array << 2 #Line No. 1
append(array = [6,4,2], n = 0) #Line No. 2
array << 0 #Line No. 1
append(array = [6,4,2,0], n = -1) #Line No. 2
return array #base case
# but `return` doesn't leave the recursion.
# it only goes up one step in the call stack, like so:
array << 0 #Line No. 3 -> array = [6,4,2,0,0]
array << 2 #Line No. 3 -> array = [6,4,2,0,0,2]
array << 4 #Line No. 3 -> array = [6,4,2,0,0,2,4]
array << 6 #Line No. 3 -> array = [6,4,2,0,0,2,4,6]
我认为Line No. 3
引入了一些混乱。如果它只是n*2
,您会看到它最终没有返回array
,而是返回Fixnum
。以下是此案例的逐步缩短版本:
append([], 3) # initial call
array << 6; append([6], 2)
array << 4; append([6,4], 1)
array << 2; append([6,4,2], 0)
array << 0; append([6,4,2,0], -1)
return array
0 # result of n*2 (Line No. 3)
2 # result of n*2 (Line No. 3)
4 # result of n*2 (Line No. 3)
6 # result of n*2 (Line No. 3)
#output = 6
另一方面,如果您删除Line No. 3
,则最后一行将是调用append
的结果,这实际上将与base case
一致。
append([], 3) # initial call
array << 6; append([6], 2)
array << 4; append([6,4], 1)
array << 2; append([6,4,2], 0)
array << 0; append([6,4,2,0], -1)
return array
array # result from the call append([6,4,2], 0) (Line No. 2)
array # result from the call append([6,4], 1) (Line No. 2)
array # result from the call append([6], 2) (Line No. 2)
array # result from the call append([], 3) (Line No. 2)
#output = [6,4,2,0]