P b*_*sak 1 ruby ruby-on-rails
我希望在递归调用期间保持变量的值为静态,例如,如果foo是一个name作为参数的函数,我想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
Run Code Online (Sandbox Code Playgroud)
第一次调用就像,run_app "john", 1我希望在调用期间保留constant_var的值.我怎样才能做到这一点?
首先,代码中存在一些冗余.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
Run Code Online (Sandbox Code Playgroud)
解决这个问题的标准方法是添加一个额外的参数来传递额外的信息:
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 Code Online (Sandbox Code Playgroud)
然后你需要调用这样的方法:
run_app(tmp = 'john', 1, tmp)
# or
run_app('john', 2, nil)
Run Code Online (Sandbox Code Playgroud)
但是,这会给调用者泄漏大量内部实现细节,并给他们带来沉重的负担.例如,他们需要知道第一个和第三个参数需要是同一个对象.但只有当他们1作为第二个论点传递时.如果他们传递的东西不是1,那么他们需要传递nil第三个参数.
什么阻止某人打电话
run_app('john', 1, 'ringo')
# or
run_app(tmp = 'john', 2, tmp)
Run Code Online (Sandbox Code Playgroud)
您可以通过使用带有默认参数的可选参数来稍微改善它:
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 Code Online (Sandbox Code Playgroud)
现在你可以像你想要的那样调用它:
run_app('john', 1)
# or
run_app('john', 2)
Run Code Online (Sandbox Code Playgroud)
但是,你仍然可以像这样调用它:
run_app('john', 1, 'ringo')
# or
run_app(tmp = 'john', 2, tmp)
Run Code Online (Sandbox Code Playgroud)
因此,我们所做的是将该逻辑移动到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 Code Online (Sandbox Code Playgroud)
像这样称呼它:
run_app('john', 1)
# or
run_app('john', 2)
Run Code Online (Sandbox Code Playgroud)
当然,你现在还可以打电话
run_app_r('john', 1, 'ringo')
# or
run_app_r(tmp = 'john', 2, tmp)
Run Code Online (Sandbox Code Playgroud)
但至少你现在有一个单独的方法,你可以清楚地记录private,例如通过使用YARD的@private标签或只是使用RDoc的:nodoc:标签完全离开文档.
run_app_r可以从任何地方调用该方法的事实,即使它只是被称为内部run_app是非常烦人的.在像Scala这样支持嵌套方法的语言中,您只需将run_app_r方法放在run_app方法中,但Ruby不支持嵌套方法,因此我们必须找到另一种方法:Procs可以嵌套在方法中!
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 Code Online (Sandbox Code Playgroud)
像这样称呼它:
run_app('john', 1)
# or
run_app('john', 2)
Run Code Online (Sandbox Code Playgroud)
由于块是闭包,我们甚至不需要明确传递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
Run Code Online (Sandbox Code Playgroud)
像这样称呼它:
run_app('john', 1)
# or
run_app('john', 2)
Run Code Online (Sandbox Code Playgroud)
但所有这一切都没有实际意义,因为你的递归没有基本情况,因此会无限循环.或者更确切地说,您将获得堆栈溢出,因为Ruby不保证正确的尾调用.
| 归档时间: |
|
| 查看次数: |
1765 次 |
| 最近记录: |