使用 bquote 时,R returnValue 在 on.exit 中不起作用
R returnValue not working in on.exit when using bquote
在使用新的 R 3.2.0 函数时 returnValue
我发现了一种行为,即使不是错误,也可能是不需要的行为。
好像returnValue
包裹在eval(bquote(on.exit(
里就不行了。见下文。
- 按应有的方式工作 - 不使用
eval(bquote(on.exit(
f <- function(x, case = 0L){
pt <- proc.time()[[3L]]
on.exit(message(paste("elapsed:",round(proc.time()[[3L]]-pt,4),"\nclass:",class(returnValue())[1L])))
Sys.sleep(0.001)
if(case==1L) rcol <- "a"
else if(case==2L) rcol <- "b"
else if(case==3L){
pt <- 100
x$a <- x$a + pt
rcol <- "a"
} else return(x)
return(x[[rcol]])
}
df <- data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = FALSE)
f(df, case=0L) # OK: expected
# elapsed: 0.001
# class: data.frame
# a b
# 1 1 a
# 2 2 b
# 3 3 c
f(df, case=1L) # OK: expected
# elapsed: 0.002
# class: integer
# [1] 1 2 3
f(df, case=2L) # OK: expected
# elapsed: 0.002
# class: character
# [1] "a" "b" "c"
f(df, case=3L) # HMMM?: not expected but still correct
# elapsed: 589.695
# class: numeric
# [1] 101 102 103
在 case=3L
上,我们可能会得到意想不到的结果,因为 pt
变量在处理过程中被覆盖了。这仍然不是问题,因为它可以正常工作。然而,我们希望在不依赖变量名称的情况下处理此类情况,这就是为什么在下面使用 bquote
。
returnValue
如果包装到 eval(bquote(on.exit(
中,总是返回 NULL
f <- function(x, case = 0L){
pt <- proc.time()[[3L]]
eval(bquote(on.exit(message(paste("elapsed:",round(proc.time()[[3L]]-.(pt),4),"\nclass:",class(returnValue())[1L])))))
Sys.sleep(0.001)
if(case==1L) rcol <- "a"
else if(case==2L) rcol <- "b"
else if(case==3L){
pt <- 100
x$a <- x$a + pt
rcol <- "a"
} else return(x)
return(x[[rcol]])
}
df <- data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = FALSE)
f(df, case=0L)
# elapsed: 0.002
# class: NULL
# a b
# 1 1 a
# 2 2 b
# 3 3 c
f(df, case=1L)
# elapsed: 0
# class: NULL
# [1] 1 2 3
f(df, case=2L)
# elapsed: NULL
# class: character
# [1] "a" "b" "c"
f(df, case=3L)
# elapsed: 0.001
# class: NULL
# [1] 101 102 103
我认为它不应该那样工作。
如何避免此类行为并在 on.exit
?
中未计算的表达式中替换值
on.exit()
只是延迟表达式评估。它在创建时不存储 pt
的值,因为它在 运行 时未被计算。如果你想 "protect" 一个值,你需要创建你自己的范围。一个函数可以有它自己的作用域。例如:
f <- function(x, case = 0L){
eptime <- local({start = proc.time()[[3L]]; function() proc.time()[[3L]]-start})
on.exit(message(paste("elapsed:",round(eptime(),4),"\nclass:",class(returnValue())[1L])))
...
}
所以这里我们用一个名为eptime
.
的函数替换函数变量pt
eval(bquote())
强制立即执行 returnValue()
,而不是在函数结束时。你没有得到你想要的延迟评估。见
f <- function(x) {
eval(bquote(on.exit(print(paste("exit", .(x))))))
x<-"ok"
print(paste("return",x))
}
f("apple")
# [1] "exit apple"
# [1] "return ok"
这样您的退出代码 运行 首先。这并非 returnValue()
所独有。
在使用新的 R 3.2.0 函数时 returnValue
我发现了一种行为,即使不是错误,也可能是不需要的行为。
好像returnValue
包裹在eval(bquote(on.exit(
里就不行了。见下文。
- 按应有的方式工作 - 不使用
eval(bquote(on.exit(
f <- function(x, case = 0L){
pt <- proc.time()[[3L]]
on.exit(message(paste("elapsed:",round(proc.time()[[3L]]-pt,4),"\nclass:",class(returnValue())[1L])))
Sys.sleep(0.001)
if(case==1L) rcol <- "a"
else if(case==2L) rcol <- "b"
else if(case==3L){
pt <- 100
x$a <- x$a + pt
rcol <- "a"
} else return(x)
return(x[[rcol]])
}
df <- data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = FALSE)
f(df, case=0L) # OK: expected
# elapsed: 0.001
# class: data.frame
# a b
# 1 1 a
# 2 2 b
# 3 3 c
f(df, case=1L) # OK: expected
# elapsed: 0.002
# class: integer
# [1] 1 2 3
f(df, case=2L) # OK: expected
# elapsed: 0.002
# class: character
# [1] "a" "b" "c"
f(df, case=3L) # HMMM?: not expected but still correct
# elapsed: 589.695
# class: numeric
# [1] 101 102 103
在 case=3L
上,我们可能会得到意想不到的结果,因为 pt
变量在处理过程中被覆盖了。这仍然不是问题,因为它可以正常工作。然而,我们希望在不依赖变量名称的情况下处理此类情况,这就是为什么在下面使用 bquote
。
returnValue
如果包装到eval(bquote(on.exit(
中,总是返回 NULL
f <- function(x, case = 0L){
pt <- proc.time()[[3L]]
eval(bquote(on.exit(message(paste("elapsed:",round(proc.time()[[3L]]-.(pt),4),"\nclass:",class(returnValue())[1L])))))
Sys.sleep(0.001)
if(case==1L) rcol <- "a"
else if(case==2L) rcol <- "b"
else if(case==3L){
pt <- 100
x$a <- x$a + pt
rcol <- "a"
} else return(x)
return(x[[rcol]])
}
df <- data.frame(a = 1:3, b = letters[1:3], stringsAsFactors = FALSE)
f(df, case=0L)
# elapsed: 0.002
# class: NULL
# a b
# 1 1 a
# 2 2 b
# 3 3 c
f(df, case=1L)
# elapsed: 0
# class: NULL
# [1] 1 2 3
f(df, case=2L)
# elapsed: NULL
# class: character
# [1] "a" "b" "c"
f(df, case=3L)
# elapsed: 0.001
# class: NULL
# [1] 101 102 103
我认为它不应该那样工作。
如何避免此类行为并在 on.exit
?
on.exit()
只是延迟表达式评估。它在创建时不存储 pt
的值,因为它在 运行 时未被计算。如果你想 "protect" 一个值,你需要创建你自己的范围。一个函数可以有它自己的作用域。例如:
f <- function(x, case = 0L){
eptime <- local({start = proc.time()[[3L]]; function() proc.time()[[3L]]-start})
on.exit(message(paste("elapsed:",round(eptime(),4),"\nclass:",class(returnValue())[1L])))
...
}
所以这里我们用一个名为eptime
.
pt
eval(bquote())
强制立即执行 returnValue()
,而不是在函数结束时。你没有得到你想要的延迟评估。见
f <- function(x) {
eval(bquote(on.exit(print(paste("exit", .(x))))))
x<-"ok"
print(paste("return",x))
}
f("apple")
# [1] "exit apple"
# [1] "return ok"
这样您的退出代码 运行 首先。这并非 returnValue()
所独有。