我的问题是:为什么不调用返回更快
它更快,因为return是R中的(原语)函数,这意味着在代码中使用它会导致函数调用的代价。与大多数其他编程语言相比,其中return是关键字,而不是函数调用:它不转换为任何运行时代码执行。
也就是说,在R中以这种方式调用原语函数非常快,并且调用return的开销非常小。这不是省略return的理由。
还是更好,因此更可取?
因为没有理由使用它。
因为它是冗余的,它没有增加有用的冗余。
需要明确的是:冗余有时是有用的。但大多数冗余都不是这样的。相反,它是那种在不增加信息的情况下增加视觉混乱的东西:它相当于一个填充词或图表垃圾)。
考虑下面的解释性注释的例子,它被普遍认为是糟糕的冗余,因为注释只是解释了代码已经表达的内容:
# Add one to the result
result = x + 1
在R中使用return也属于同一类别,因为R是一种函数式编程语言,在R中每个函数调用都有一个值。这是R的一个基本属性,一旦你从每个表达式(包括每个函数调用)都有一个值的角度看R代码,问题就变成了:“为什么我要使用return?”需要有一个积极的理由,因为默认是不使用它。
其中一个积极的原因是在一个guard子句中提早退出函数:
f = function (a, b) {
if (! precondition(a)) return() # same as `return(NULL)`!
calculation(b)
}
这是一个有效的、非冗余的return用法。然而,与其他语言相比,这样的保护子句在R中很少,而且由于每个表达式都有一个值,正则if不需要return:
sign = function (num) {
if (num > 0) {
1
} else if (num < 0) {
-1
} else {
0
}
}
我们甚至可以这样重写f:
f = function (a, b) {
if (precondition(a)) calculation(b)
}
这里if (cond) expr与if (cond) expr else NULL相同。
最后,我想先说三个常见的反对意见:
Some people argue that using return adds clarity, because it signals “this function returns a value”. But as explained above, every function returns something in R. Thinking of return as a marker of returning a value isn’t just redundant, it’s actively misleading.
Relatedly, the Zen of Python has a marvellous guideline that should always be followed:
Explicit is better than implicit.
How does dropping redundant return not violate this? Because the return value of a function in a functional language is always explicit: it’s its last expression. This is again the same argument about explicitness vs redundancy.
In fact, if you want explicitness, use it to highlight the exception to the rule: mark functions that don’t return a meaningful value, which are only called for their side-effects (such as cat). Except R has a better marker than return for this case: invisible. For instance, I would write
save_results = function (results, file) {
# … code that writes the results to a file …
invisible()
}
But what about long functions? Won’t it be easy to lose track of what is being returned?
Two answers: first, not really. The rule is clear: the last expression of a function is its value. There’s nothing to keep track of.
But more importantly, the problem in long functions isn’t the lack of explicit return markers. It’s the length of the function. Long functions almost (?) always violate the single responsibility principle and even when they don’t they will benefit from being broken apart for readability.