首先,您的代码中有一些冗余。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)
但是,这会将大量内部实现细节泄露给调用者,并给他们带来沉重的负担。例如,他们需要知道第一个和第三个参数必须是同一个对象。但前提是它们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 不支持嵌套方法,因此我们必须找到另一种方法:Proc
s 可以嵌套在方法内部!
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
像这样称呼它:
run_app('john', 1)
# or
run_app('john', 2)
但这一切都没有实际意义,因为您的递归没有基本情况,因此将无限循环。或者更确切地说,您将得到堆栈溢出,因为 Ruby 不保证正确的尾调用。