在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.我想这是一个bug,因为在Windows上,它的工作原理。 (注意:我在Linux上使用R 3.1.2,在Windows上使用R 3.1.1。)
问题:这是一个错误吗?如果是的话,一个已知的bug?是否有一个简单的解决方案,不需要重构代码?
谢谢!
编辑:使用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))
答案 0 :(得分:2)
事实上,这在Windows下无意中起作用,因为mclapply
未在Windows下定义,而只是调用lapply
。
的确,当你打电话给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
:
library(parallel)
res <- mclapply(1:2, function(x){a<<- 20;x})
a
[1] 4
a未改变且仍然等于4.这是正常的并列行为,因为我们避免产生副作用。在mcapply
下,只需调用lapply
,即可正确更改全局变量的值。
如果您想要全局副作用,最好使用lapply
,但如果您将a
作为第二个参数添加到函数中,您可以在阅读中模拟全局变量... < / p>
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)