使用 tm 在 R 函数中分配全局变量:linux 上的错误?

assign global variable in R function using tm: bug on linux?

使用 R 中的包 tm,我想转换一个具有相当复杂功能的语料库,我需要一些副作用来存储相关信息。由于 content_transformer 需要特定的函数格式,因此简单的方法是在我的函数中使用 <<-。以下代码出现问题:

library(tm)
a <- 4
n <- 2
corp<-VCorpus(VectorSource(rep("fish",n)))
(func<-content_transformer(
  function(x) {
    a <<- 42
    return(x)
}))
corp<-tm_map(corp,func)
print(a)

它打印出错误的答案,即 4。但是当 n=1 时,它打印出正确的答案。所以我假设是 tm 执行的多线程无法像标量 R 那样工作。我猜这是一个错误,因为在 windows 上它起作用了。 (注意:我在 linux 上使用 R 3.1.2,在 windows 上使用 R 3.1.1)。

问题:这是一个错误吗?如果是,一个已知的错误?有没有不需要重构代码的简单解决方案?

谢谢!


编辑:使用 assing

的附加示例
rm(list=ls())
library(tm)
env <- new.env()
a <- 1
n <- 2
corp<-VCorpus(VectorSource(rep("fish",n)))
(func<-content_transformer(
  function(x,e) {
    assign("a", 42, envir=e)
    print(e)
    print(ls.str(e))
    return(x)
}))
corp<-tm_map(corp,func,env)
print(env)
print(ls.str(env))

事实上,这在 Windows 下意外起作用,因为 mclapply 未在 windows 下定义,它只是对 lapply.[=21= 的调用]

确实,当您调用 tm_map 时,您正在使用此函数:

tm:::tm_map.VCorpus
function (x, FUN, ..., lazy = FALSE) 
{
    if (lazy) {
        fun <- function(x) FUN(x, ...)
        if (is.null(x$lazy)) 
            x$lazy <- list(index = rep(TRUE, length(x)), maps = list(fun))
        else x$lazy$maps <- c(x$lazy$maps, list(fun))
    }
    else x$content <- mclapply(content(x), FUN, ...) ## this the important line
    x
}

因此您可以通过调用 mclapply 重现 "odd/normal" 行为:

library(parallel)
res <- mclapply(1:2, function(x){a<<- 20;x})

a
[1] 4

a 没有变化,仍然等于 4。这是正常的并行行为,因为我们避免了副作用。在 windows mcapply 下只是对 lapply 的调用,因此全局变量的值被正确更改。

伪解

如果你想要全局副作用,这里最好使用 lapply,但是如果你添加 a 作为函数的第二个参数,你可以在阅读中模拟全局变量。 .

func <- 
  function(x,a) {   
    a <- 42      ## use a here 
    x$a <- a     ## assign it to the x environment 
    return(x)    ## but the new value of a can not be used by others documents..
  }
(Func<-content_transformer(func))
res <- tm_map(corp,Func,a=4)