Din*_*nre 22
您遇到麻烦的原因是您将对象传递到函数的本地命名空间.这是关于R的伟大/可怕的事情之一:它允许隐式变量声明,然后在命名空间变得更深时实现超越.
这会影响您,因为函数在当前命名空间中创建新的命名空间.我认为,对象'myTable'最初是在全局命名空间中创建的,但是当它传递给函数'title.asterisk'时,新的函数本地命名空间现在有一个具有相同属性的对象.这样工作如下:
title.asterisk <- function(myTable){ do some stuff to 'myTable' }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,函数'title.asterisk'不会对全局对象'myTable'进行任何更改.而是使用相同的名称创建本地对象,因此本地对象取代全局对象.如果我们title.asterisk(myTable)以这种方式调用函数,该函数仅对局部变量进行更改.
有两种直接的方法来修改全局对象(以及许多间接方式).
选项1:首先,如您所述,让函数返回对象并覆盖全局对象,如下所示:
title.asterisk <- function(myTable){
do some stuff to 'myTable'
return(myTable)
}
myTable <- title.asterisk(myTable)
Run Code Online (Sandbox Code Playgroud)
这没关系,但你仍然使你的代码有点难以理解,因为实际上有两个不同的'myTable'对象,一个是全局的,一个是函数的局部对象.许多程序员通过添加句号''来清除这一点.在变量参数前面,如下所示:
title.asterisk <- function(.myTable){
do some stuff to '.myTable'
return(.myTable)
}
myTable <- title.asterisk(myTable)
Run Code Online (Sandbox Code Playgroud)
好的,现在我们有一个视觉提示,两个变量是不同的.这很好,因为当我们稍后尝试调试我们的代码时,我们不想依赖名称空间超越等不可见的东西.它只会使事情变得更加艰难.
选项2:您可以从函数中修改对象.当您想对对象进行破坏性编辑并且不希望内存膨胀时,这是更好的选择.如果您正在进行破坏性编辑,则无需保存原始副本.此外,如果您的对象适当大,您不希望在不需要时复制它.要编辑全局命名空间对象,只需将其传递给函数或从函数中声明它.
title.asterisk <- function(){ do some stuff to 'myTable' }
Run Code Online (Sandbox Code Playgroud)
现在我们从函数中直接编辑对象'myTable'.我们没有传递对象的事实使我们的函数看起来更高级别的命名空间来尝试解析变量名称.瞧,它发现一个'myTable'对象更高了!函数中的代码对对象进行更改.
要考虑的注意事项:我讨厌调试.我的意思是我真的讨厌调试.这对我来说意味着一些事情:
Mar*_*gan 10
正如你所指出的那样,这两种范式正在取代整个对象,或者写出"替换"函数,例如
`updt<-` <- function(x, ..., value) {
## x is the object to be manipulated, value the object to be assigned
x$lbl <- paste0(x$lbl, value)
x
}
Run Code Online (Sandbox Code Playgroud)
同
> d <- data.frame(x=1:5, lbl=letters[1:5])
> d
x lbl
1 1 a
2 2 b
3 3 c
> updt(d) <- "*"
> d
x lbl
1 1 a*
2 2 b*
3 3 c*
Run Code Online (Sandbox Code Playgroud)
例如,这是对$<-就地访问的元素进行就地更新的行为$.这是一个相关的问题.人们可以将替代函数视为语法糖
updt1 <- function(x, ..., value) {
x$lbl <- paste0(x$lbl, value)
x
}
d <- updt1(d, value="*")
Run Code Online (Sandbox Code Playgroud)
但是在我看来,标签"语法糖"对于所涉及的核心范式并没有真正公正.它实现了方便的就地更新,这与R通常维护的更改时的错觉不同,它实际上是更新对象的"R"方式(而不是使用?ReferenceClasses,例如,更多的更新对象)其他语言的感觉,但会让R用户期待复制更改语义.