从 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 语法,我可以很容易地计算出大量的组合;但是当使用向量赋值时,任何超过四个元素都会导致递归混乱,从而破坏系统。

所以我想问题是,

  1. 为什么在同一个地方调用它们时,它似乎比 print 函数更频繁地触发向量赋值?

  2. 有没有更好的方法来实现这种功能?

perm 函数基于 this blog post 中的函数之一。

  1. 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"