我希望在递归调用期间保持变量的值为静态,例如,如果foo
是一个以name
为参数的函数,我想保存{{1}的值从变量中第一次调用name
开始,变量将在每次递归调用foo时保留该值。
foo
第一次调用就像def run_app (name, startr)
if startr==1
constant_var=name
end
some_name = modify name
diff = compare some_name, constant_var
# recursive call
run_app some_name, 0
end
我希望在调用期间保留constant_var的值。我怎样才能做到这一点?
答案 0 :(得分:5)
首先,您的代码中存在一些冗余。已分配diff
但从未使用过。你可以摆脱它:
def run_app(name, startr)
constant_var = name if startr == 1
some_name = modify name
compare(some_name, constant_var)
# recursive call
run_app(some_name, 0)
end
解决这个问题的标准方法是添加一个额外的参数来传递额外的信息:
def run_app(name, startr, constant_var)
some_name = modify name
compare(some_name, constant_var)
# recursive call
run_app(some_name, 0, constant_var)
end
然后你需要调用这样的方法:
run_app(tmp = 'john', 1, tmp)
# or
run_app('john', 2, nil)
然而,这会将 ton 的内部实现细节泄漏给调用者,并给他们带来沉重的负担。例如,他们需要知道第一个和第三个参数需要是同一个对象。但只有当他们通过1
作为第二个参数时。如果他们传递的内容不是1
,那么他们需要传递nil
作为第三个参数。
阻止某人打电话
的是什么run_app('john', 1, 'ringo')
# or
run_app(tmp = 'john', 2, tmp)
通过使用带有默认参数的可选参数,您可以稍微改善一下:
def run_app(name, startr, constant_var = name if startr == 1)
some_name = modify name
compare(some_name, constant_var)
# recursive call
run_app(some_name, 0, constant_var)
end
现在您可以按照以下方式调用它:
run_app('john', 1)
# or
run_app('john', 2)
但是,你可以仍然这样称呼它:
run_app('john', 1, 'ringo')
# or
run_app(tmp = 'john', 2, tmp)
因此,我们所做的是将该逻辑转移到private
辅助方法中,并为公共方法提供我们想要的API:
def run_app(name, startr)
constant_var = name if startr == 1
run_app_r(name, startr, constant_var)
end
private
def run_app_r(name, startr, constant_var)
some_name = modify name
compare(some_name, constant_var)
# recursive call
run_app_r(some_name, 0, constant_var)
end
这样称呼:
run_app('john', 1)
# or
run_app('john', 2)
当然,您现在可以仍调用
run_app_r('john', 1, 'ringo')
# or
run_app_r(tmp = 'john', 2, tmp)
但至少你现在有一个单独的方法,你可以清楚地记录为private
,例如使用YARD的@private
标记,或者只使用RDoc的:nodoc:
标记将其完全排除在文档之外。
run_app_r
方法可以从任何地方调用,即使它只是在run_app
内调用,这是非常烦人的事实。在像Scala这样支持嵌套方法的语言中,您只需将run_app_r
方法放在run_app
方法中,但Ruby不支持嵌套方法,因此我们必须找到另一种方法:{{1 s可以嵌套在方法中!
Proc
这样称呼:
def run_app(name, startr)
constant_var = name if startr == 1
(run_app_r = ->(name, startr, constant_var; some_name) {
some_name = modify name
compare(some_name, constant_var)
# recursive call
run_app_r.(some_name, 0, constant_var)
}).(name, startr, constant_var)
end
由于块是闭包,我们甚至不需要明确地传递run_app('john', 1)
# or
run_app('john', 2)
:
constant_var
这样称呼:
def run_app(name, startr)
constant_var = name if startr == 1
(run_app_r = ->(name, startr; some_name) {
some_name = modify name
compare(some_name, constant_var)
# recursive call
run_app_r.(some_name, 0)
}).(name, startr)
end
但所有这一切都没有实际意义,因为你的递归没有基本情况,因此会无限循环。或者更确切地说,您将获得堆栈溢出,因为Ruby不保证正确的尾调用。
答案 1 :(得分:0)
我会使用修改名称的参数:
def run_app (name, modified_name=name)
# do something with name
modified_name = modify(name)
# recursive call
run_app name, modified_name
end
然后,您可以使用run_app("John")
答案 2 :(得分:0)
一种方法是在递归调用中编写一个包装器,它在调用实际函数之前将变量存储在某处。也许作为你班级的成员变量。
def run_wrapper(name, startr)
@orig_name = name
run_app (name, startr)
end
def run_app(name, startr)
p @orig_name
end
更简洁的方法可能是添加第三个参数
def run_app(name, startr, orig_name = nil)
...
run_app("blah", startr-1, orig_name || name)
end