从 R 中的递归函数编译向量
Compiling a vector from a recursive function in R
我正在尝试了解作用域在 R 中的递归函数中是如何工作的。
上下文是这个函数,它应该 return 向量元素的所有唯一组合。 (确切所需输出的详细信息在这里并不真正相关。)
perm <- function(x) {
n <- length(x)
if (n == 1) {
print(x)
} else {
y <- NULL
for (i in 1:n) {
y <- paste(x[i], perm(x[-i]), sep = "_")
}
print(y)
}
}
当我打印我知道我想要 returned 的对象时(这里是 print(x)
和 print(y)
),我得到了正确的值 returned到控制台就像打印输出一样:
perm(c("a","b","c"))
但是,当我尝试将这些收集到向量中时,生成的向量包含的元素比打印出来的要多很多个数量级。我怀疑这与递归有关,但考虑到 print
函数只是被合理地触发,这似乎很奇怪。例如,并使用全局变量来跟踪输出以忽略任何范围问题:
out <- c()
perm <- function(x) {
n <- length(x)
if (n == 1) {
assign('out', c(out, x), envir = .GlobalEnv)
} else {
y <- NULL
for (i in 1:n) {
y <- paste(x[i], perm(x[-i]), sep = "_")
}
assign('out', c(out, y), envir = .GlobalEnv)
}
}
perm(c("a","b","c"))
out
第一个示例仅打印十个值,而在第二个示例中,out
的长度为 56,并且包含在第一个示例中找不到的值(例如,"c_c"
)。我知道以这种方式分配向量的效率非常低,但我只是想弄清楚范围界定是如何工作的,以及为什么这些结果如此不同。我不会想到 print
函数会有任何范围问题,即每次 print(x)
或 print(y)
被触发时,我希望输出被打印到控制台。
当我将 out
分配给父框架而不是全局环境时,也会发生同样的事情,即 out <<- c(out, x)
。有趣的是,如果我只使用 print
语法,我可以很容易地计算出大量的组合;但是当使用向量赋值时,任何超过四个元素都会导致递归混乱,从而破坏系统。
所以我想问题是,
为什么在同一个地方调用它们时,它似乎比 print
函数更频繁地触发向量赋值?
有没有更好的方法来实现这种功能?
perm
函数基于 this blog post 中的函数之一。
- Why does it seem to be triggering the vector assignment more frequently that the print function, when they're called in the same place?
问题是 print
returns 第一个参数,而 assign
returns 赋值。取:
b <- assign("a", 2)
b
#R> [1] 2
因此,您的函数应该是:
out <- c()
perm <- function(x) {
n <- length(x)
if (n == 1) {
assign('out', c(out, x), envir = .GlobalEnv)
x
} else {
y <- NULL
for (i in 1:n) {
y <- paste(x[i], perm(x[-i]), sep = "_")
}
assign('out', c(out, y), envir = .GlobalEnv)
y
}
}
perm(c("a","b","c"))
#R> [1] [1] "c_b_a"
out
#R> [1] "c" "b" "c_b" "c" "a" "c_a" "b" "a" "b_a" "c_b_a"
我正在尝试了解作用域在 R 中的递归函数中是如何工作的。
上下文是这个函数,它应该 return 向量元素的所有唯一组合。 (确切所需输出的详细信息在这里并不真正相关。)
perm <- function(x) {
n <- length(x)
if (n == 1) {
print(x)
} else {
y <- NULL
for (i in 1:n) {
y <- paste(x[i], perm(x[-i]), sep = "_")
}
print(y)
}
}
当我打印我知道我想要 returned 的对象时(这里是 print(x)
和 print(y)
),我得到了正确的值 returned到控制台就像打印输出一样:
perm(c("a","b","c"))
但是,当我尝试将这些收集到向量中时,生成的向量包含的元素比打印出来的要多很多个数量级。我怀疑这与递归有关,但考虑到 print
函数只是被合理地触发,这似乎很奇怪。例如,并使用全局变量来跟踪输出以忽略任何范围问题:
out <- c()
perm <- function(x) {
n <- length(x)
if (n == 1) {
assign('out', c(out, x), envir = .GlobalEnv)
} else {
y <- NULL
for (i in 1:n) {
y <- paste(x[i], perm(x[-i]), sep = "_")
}
assign('out', c(out, y), envir = .GlobalEnv)
}
}
perm(c("a","b","c"))
out
第一个示例仅打印十个值,而在第二个示例中,out
的长度为 56,并且包含在第一个示例中找不到的值(例如,"c_c"
)。我知道以这种方式分配向量的效率非常低,但我只是想弄清楚范围界定是如何工作的,以及为什么这些结果如此不同。我不会想到 print
函数会有任何范围问题,即每次 print(x)
或 print(y)
被触发时,我希望输出被打印到控制台。
当我将 out
分配给父框架而不是全局环境时,也会发生同样的事情,即 out <<- c(out, x)
。有趣的是,如果我只使用 print
语法,我可以很容易地计算出大量的组合;但是当使用向量赋值时,任何超过四个元素都会导致递归混乱,从而破坏系统。
所以我想问题是,
为什么在同一个地方调用它们时,它似乎比
print
函数更频繁地触发向量赋值?有没有更好的方法来实现这种功能?
perm
函数基于 this blog post 中的函数之一。
- Why does it seem to be triggering the vector assignment more frequently that the print function, when they're called in the same place?
问题是 print
returns 第一个参数,而 assign
returns 赋值。取:
b <- assign("a", 2)
b
#R> [1] 2
因此,您的函数应该是:
out <- c()
perm <- function(x) {
n <- length(x)
if (n == 1) {
assign('out', c(out, x), envir = .GlobalEnv)
x
} else {
y <- NULL
for (i in 1:n) {
y <- paste(x[i], perm(x[-i]), sep = "_")
}
assign('out', c(out, y), envir = .GlobalEnv)
y
}
}
perm(c("a","b","c"))
#R> [1] [1] "c_b_a"
out
#R> [1] "c" "b" "c_b" "c" "a" "c_a" "b" "a" "b_a" "c_b_a"