【问题标题】:Basics of argument passing in R's functionsR 函数中参数传递的基础知识
【发布时间】:2017-06-07 04:39:36
【问题描述】:

R如何解释以下函数定义中的行:arg.list <- list(x, y),它是在执行时将xy复制到arg.list对象中还是通过引用传递?

fplot <- function(x, y, add=FALSE){
  arg.list <- list(x, y)
  if(!add){
    plot(arg.list))
  }else{
    lines(arg.list)
  }
}

【问题讨论】:

  • 请注意,您当前的问题与传递给函数的参数无关(如标题所示),而是从标量向量变量构造容器变量...这真的是您的意图吗?
  • @R Yoda,在我的实际功能中,xydata.frame,然后我像这样使用它们:x$var1
  • x 和 y 如果您在函数外部或内部修改它,肯定会被复制(在此之前,“第一次修改时复制”仍然是正确的,以避免不必要的内存复制)。 x$var 产生一个向量...

标签: r functional-programming parameter-passing pass-by-reference


【解决方案1】:

变量通过引用嵌入到列表中(至少如果您使用向量)。

证明:

library(pryr)

x <-   1:100
y <- 201:200

arg.list <- list(x,y)

al.x <- arg.list[[1]]
al.y <- arg.list[[2]]

现在看看内存地址(它们是一样的):

> address(x)
[1] "0x37598c0"
> address(y)
[1] "0x40fd6f8"
> address(al.x)
[1] "0x37598c0"
> address(al.y)
[1] "0x40fd6f8"

如果您更改一项,则会创建一个副本(“修改时复制”):

> x[1]=42
> address(x)
[1] "0x417a470"
> al.x <- arg.list[[1]]
> address(al.x)
[1] "0x37598c0"

编辑:

正如@HongOoi 所说:R 在语义上从不使用引用(环境类中的对象除外),而是为变量使用副本。它“足够聪明地避免复制,直到真正需要它们”(“在[第一次]修改时复制”)。函数参数在语义上“按值”传递(即使在修改发生之前使用引用)。

【讨论】:

    【解决方案2】:

    R 的语义是函数参数总是按值传递。底层实现可能不一定要对参数进行新副本,以节省内存。但是您的函数会表现得好像它有全新的副本可供使用。

    这意味着您不必担心在函数外部更改变量,因为您在内部进行了更改:

    x <- 1
    f <- function(z) {
        z <- z + 1
        z
    }
    
    y <- f(x)
    print(y)  # y now contains 2
    print(x)  # but x still contains 1
    

    如果 R 是按引用传递的,那么修改 f 的参数也会修改传入的变量。这不会发生。

    【讨论】:

    • 那么 R Yoda 的回答呢?
    • Yoda 的回答是关于 R 的内部结构。除非需要,否则不复制参数是很聪明的。例如,如果我的函数f 根本没有修改它的参数:f &lt;- function(z) { return(z + 1) },那么它就不会费心制作z 的新副本。但是,f 的外在行为始终好像创建了参数的新副本。
    • R 在某些领域是通过引用传递的,即环境。稍后我可能会将其添加到答案中。
    • 我明白了,但是我的例子呢,在哪里,没有修改,只有合成? @R Yoda 说它适用于向量,是否适用于其他对象?
    • 问题的当前措辞模棱两可。 OP 是否想知道函数参数是如何传递的(正如标题所暗示的那样),或者对象组合是通过 ref 还是通过 value 完成的? @Qbik请澄清这一点。我不得不承认,HongOoi 的你的回答更合适,因为它更好地解释了内部结构:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2014-06-20
    • 2013-02-24
    • 1970-01-01
    相关资源
    最近更新 更多