我有一些R代码:
time.read = system.time(df <- data.frame(fread(f)))
print(class(time.read))
#[1] "proc_time"
print(class(df))
#[1] "data.frame"
Run Code Online (Sandbox Code Playgroud)
不知何故,当执行此操作时,在主R环境/范围中:
我认为函数内部创建的变量在函数范围之外是不可用的?这是如何运作的?为什么运行以下内容后主R环境中不存在?
fx <- function(z){return(1)}
out = fx(y <- 300)
print(out)
#[1] 1
print(y)
#Error in print(y) : object 'y' not found
Run Code Online (Sandbox Code Playgroud)
谢谢!
Kon*_*lph 18
好问题!R做了一些与其论点特有的东西,这引起了很多混乱,但也非常有用.
当您将参数传递给R中的函数时,在函数内部实际使用它之前不会对其进行求值.在此之前,参数只是在一个名为promise的特殊容器中.Promise拥有一个表达式和它们应该被评估的环境 - 对于参数,这就是调用者的环境.
但是只要在函数内部使用参数,就会计算其值.这是怎么回事system.time.简化:
system.time = function (expr) {
before = proc.time()
expr
proc.time() - before
}
Run Code Online (Sandbox Code Playgroud)
换句话说,该函数只是在查看其参数之前记录时间.然后它查看其参数,从而导致其评估,然后记录经过的时间.但请记住,参数的评估发生在调用者的作用域中,因此在您的情况下,赋值(df)的目标在父作用域中也是可见的.
在你的第二个例子中,你的函数fx从不查看它的参数,因此它永远不会被评估.您可以轻松地更改它,只需使用它就可以强制评估其参数:
fx <- function(z) {
z
return(1)
}
Run Code Online (Sandbox Code Playgroud)
实际上,R具有特殊功能 - force为此目的:
fx <- function(z) {
force(z)
return(1)
}
Run Code Online (Sandbox Code Playgroud)
但force它只是语法糖,它的定义只是返回它的论点:
force = function (x) x
Run Code Online (Sandbox Code Playgroud)
R不立即评估其参数的事实很有用,因为您还可以在函数内检索未评估的表单.这称为
非标准评估,它有时用于评估不同范围内的表达式(使用指定eval了其参数的函数envir),或检索有关未评估表达式的信息.
许多函数最突出地使用它,plot它根据绘制的变量/表达式猜测默认轴标签:
x = seq(0, 2 * pi, length.out = 100)
plot(x, sin(x))
Run Code Online (Sandbox Code Playgroud)
现在轴标签是x和sin(x).该plot函数知道这一点,因为在其中,它可以查看其函数参数的未评估表达式:
xlabel = deparse(substitute(x))
ylabel = deparse(substitute(y))
Run Code Online (Sandbox Code Playgroud)
substitute检索未评估的表达式.
deparse将其转换为字符串表示形式.