Suppose I have a list containing functions:
假设我有一个包含函数的列表:
funcs <- list(
loop = function(n) {
result <- 0
for (i in seq_len(n)) {
result <- result + i
}
result
},
vect = function(n) sum(seq_len(n))
)
If I want to benchmark them using bench
I can do this:
如果我想使用BASCH对它们进行基准测试,我可以这样做:
N <- 1e6
bench::mark(funcs$loop(N), funcs$vect(N)) # Ok
which works fine. However, I have two minor nits with this approach.
它运行得很好。然而,我对这种方法有两个小毛病。
- I need to remember to write an expression for each function. For example, if I add a function to
funcs
I need to remember to also add it as an expression to mark(...)
.
- I'm also repeating the evaluation of the function (i.e.,
(N)
is repeated more than once). Obviously it's trivial here, but it's a form of repetition all the same.
It seems that the exprs
argument to mark
should help by allowing me to do something like:
看来,Exprs对Mark的论证应该会有所帮助,因为它允许我做一些类似的事情:
bench::mark(exprs = lapply(funcs, \(f) expression(f(1e6)))) # Error in f(1e+06) : could not find function "f"
However, it generates an error. How can I generate a list suitable for passing to the exprs
argument?
但是,它会生成一个错误。如何生成适合传递给exprs参数的列表?
更多回答
You can use bquote()
or substitute()
instead of expression()
. Either way you’ll need to let the function know to un-quote the function.
您可以使用BQUOTE()或SUBSITE()来代替表达式()。无论采用哪种方法,您都需要让函数知道取消对函数的引用。
bquote
results in the same error, while substitute
results in the error message "Error in eval(e, env) : object 'X' not found". I suspect I'm not understanding your second sentence (i.e., where you mention unquoting).
BQUOTE会导致相同的错误,而替换会导致错误消息“ERROR in val(e,env):Object‘X’Not Found”(错误在val(e,env):找不到对象‘X’)。我想我没有理解你的第二句话(即你提到的引语)。
It turns out that bench::mark(exprs = lapply(funcs, \(f) { g <- f; substitute(g(1e6)) }))
works. So clearly it has something to do with how a variable is captured (I've seen a similar problem in C# when closing over a loop variable). However, I can't say I fully understand the issue. At least it's a solution!
结果证明BASE::MARK(exprs=lapp(uncs,\(F){g<-f;subite(g(1e6))}))是有效的。因此,很明显,这与如何捕获变量有关(我在C#中看到过类似的问题,当结束循环变量时)。然而,我不能说我完全理解这个问题。至少这是一个解决方案!
优秀答案推荐
Instead of using expression()
one needs to use subsititute()
(as indicated by Konrad Rudolph). However, as originally written, it captures the wrong parameter; reassigning to a temporary variable fixes this. Thus the following code works.
我们不需要使用表达式(),而需要使用sidiute()(如康拉德·鲁道夫所指出的)。但是,正如最初编写的那样,它捕获了错误的参数;重新分配给临时变量可以解决这个问题。因此,以下代码可以正常工作。
bench::mark(exprs = lapply(funcs, \(f) {
g <- f
substitute(g(1e6))
}))
更多回答
我是一名优秀的程序员,十分优秀!