38

This post (Lazy evaluation in R – is assign affected?) covers some common ground but I am not sure it answers my question.

I stopped using assign when I discovered the apply family quite a while back, albeit, purely for reasons of elegance in situations such as this:

names.foo <- letters
values.foo <- LETTERS
for (i in 1:length(names.foo))
  assign(names.foo[i], paste("This is: ", values.foo[i]))

which can be replaced by:

foo <- lapply(X=values.foo, FUN=function (k) paste("This is :", k))
names(foo) <- names.foo

This is also the reason this (http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f) R-faq says this should be avoided.

Now, I know that assign is generally frowned upon. But are there other reasons I don't know? I suspect it may mess with the scoping or lazy evaluation but I am not sure? Example code that demonstrates such problems will be great.

4

3 回答 3

35

实际上这两种操作是完全不同的。第一个给你 26 个不同的对象,而第二个给你一个。第二个对象将更容易在分析中使用。所以我想我会说你已经证明了 的主要缺点assign,即必须始终使用get来收集或收集所有名称相似的单个对象,这些对象现在在全球环境中“松散”。试着想象一下你将如何对这 26 个独立的对象进行连续的处理。对于第二种策略,一个简单lapply(foo, func)的就足够了。

那个常见问题引用实际上只是说使用分配然后分配名称更容易,但并不意味着它是“坏的”。我碰巧把它读作“功能较少”,因为您实际上并没有返回一个被分配的值。该效果看起来是一种副作用(在这种情况下,该assign策略会产生 26 个单独的副作用)。使用assign似乎被来自具有全局变量的语言的人采用,作为避免采用“真正的 R 方式”的一种方式,即使用数据对象进行函数式编程。他们真的应该学习使用列表,而不是在他们的工作空间里乱扔单独命名的项目。

还有另一种可以使用的分配范式:

 foo <- setNames(  paste0(letters,1:26),  LETTERS)

这会创建一个命名的原子向量而不是命名列表,但是对向量中值的访问仍然是使用给定的名称来完成的[

于 2013-07-09T22:53:35.410 回答
14

作为来源,fortune(236)我想我会添加几个示例(另请参见 参考资料fortune(174))。

首先,一个测验。考虑以下代码:

x <- 1
y <- some.function.that.uses.assign(rnorm(100))

运行上面两行代码后, 的值是x多少?

assign函数用于提交“远距离行动”(参见http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming)或谷歌)。这通常是难以找到错误的根源。

我认为最大的问题assign是它往往会导致人们走上思考的道路,使他们远离更好的选择。一个简单的例子是问题中的 2 组代码。该lapply解决方案更优雅,应该得到推广,但人们了解该功能这一事实assign会导致人们选择循环选项。然后他们决定他们需要对循环中创建的每个对象执行相同的操作(这将只是另一个简单的lapply或者如果使用了优雅的解决方案)并sapply诉诸一个更复杂的循环,其中包括对. 然后那些迷恋尝试做类似的事情:getapplypasteassign

curname <- paste('myvector[', i, ']')
assign(curname, i)

这并没有达到他们的预期,这导致要么抱怨 R(这就像抱怨我隔壁邻居的房子太远,因为我选择绕着街区走很长的路一样公平),或者更糟糕的是,钻研使用evalandparse让他们构造的字符串“工作”(然后导致fortune(106)and fortune(181))。

于 2013-07-10T16:30:08.810 回答
8

我想指出这assign意味着要与environments 一起使用。

从这个角度来看,上面示例中的“坏”事情是使用了不太合适的数据结构(基础环境而不是listor data.frame, vector, ...)。

旁注:对于environments,$and$<-运算符也有效,因此在许多情况下,显式assignget也不是必需的。

于 2013-07-10T06:58:40.993 回答