我正在试验R中的声明性编程范例。我已经定义了一个函数,它将从 n 到 m 的整数序列求和。当我使用sum()
时,该函数返回预期的结果:
> sumRange <- function(n, m) if (n <= m) return(sum(n, sumRange((n+1), m)))
> sumRange(1, 10)
[1] 55
但是,当我使用+
运算符时,函数返回numeric(0)
:
> sumRange <- function(n, m) if (n <= m) return(n + sumRange((n+1), m))
> sumRange(1, 10)
numeric(0)
为什么运算符+
在这个递归函数中不起作用?有没有办法重写函数,以便它呢?
答案 0 :(得分:1)
问题是你从不指定else条件,因此在递归结束时,当NULL
条件失败时,R似乎返回if
。返回0作为else条件可以解决您的问题:
sumRange <- function(n, m) return(ifelse (n <= m, (n + sumRange((n+1), m)), 0))
sumRange(1, 10)
[1] 55
请注意,这主要是为递归定义基本情况。一个基本案例,当命中时,结束递归并导致堆栈上的调用被解开。
要查看代码编写方式的问题,请尝试明确写出您的函数:
sumRange <- function(n, m) {
if (n <= m) {
return(n + sumRange((n+1), m))
}
// but what gets returned if n > m ?
// this is undefined behavior
}
我不是R大师,但我的理解是R是用C语言编写的,而C可能允许这样的递归而没有else
条件。但是行为没有明确定义,你不应该依赖它。
答案 1 :(得分:1)
如果没有返回(使用显式或隐式返回语句),则R函数似乎返回NULL
对象。
如果您向此对象添加数值,它将只返回numeric(0)
。
所以,在第二种情况下发生的情况是,当n
达到11时,它返回一个NULL
对象,并返回向其添加值。但是NULL + 10 + 9 .. = numeric(0)
。
使用
进行检查no_ret <- function ()
{
# just return nothing
}
obj <- no_ret()
obj
# NULL
class(obj)
# "NULL
new_obj <- obj + 10
new_obj
# numeric(0)
执行第一个函数时,sum语句得到的是
其中包含NULL
的向量。例如,
vec <- c(NULL, 10, 9,...)
实际上是vec <- c(10, 9, ...)
,因此您可以获得预期的结果。
> c(NULL, 10:1)
[1] 10 9 8 7 6 5 4 3 2 1
> sum(NULL, 10:1)
[1] 55
> NULL + 10:1
integer(0)