我最近在我的R教程中遇到了这个例子:
sapply(list(runif (10), runif (10)),
function(x) c(min = min(x), mean = mean(x), max = max(x))
我的印象是,在function()-函数中,您首先必须在括号内列出您的参数,然后在大括号内列出函数执行的操作。
在这个例子中,有"no"大括号,代码似乎无论如何都可以运行,这怎么可能?
这是一个单一的语句,因此不需要任何括号
sapply(0:5, function(x) x + 5)
但是,如果函数需要多个语句,则可以在大括号内分隔每个语句
sapply(0:5, function(x) {
x <- sequence(x)
x1 <- x[x > 2]
c(mean = mean(x1), min = min(x1))
})
正如@qdread评论中提到的,一个好的做法是包括卷曲,尽管可能会有轻微的效率下降
library(microbenchmark)
microbenchmark(nocurly = sapply(0:1e6, function(x) x + 5),
curly = sapply(0:1e6, function(x) {x + 5}))
#Unit: milliseconds
# expr min lq mean median uq max neval
# nocurly 666.2539 922.0929 928.6206 942.9065 966.8318 1113.828 100
# curly 710.8450 925.7917 947.7641 955.2041 973.8009 1081.597 100
function
是一个原始函数:
`function`
.Primitive("function")
它的第二个参数是主体,它是一个引用函数,这意味着第二个参数不会被计算。这些是等效的:
fun1 <- function(x) x + 5
fun2 <- `function`(NULL, x + 5)
formals(fun2) <- alist(x=)
fun3 <- do.call( 'function', list(as.pairlist(alist(x=)), quote(x+5)))
identical(fun1,fun2)
[1] TRUE
identical(fun1,fun3)
[1] TRUE
请参阅这个问题,解决为什么我们不能像使用其他函数那样使用函数function
:如何调用"函数"函数?
用于fun1
的语法是function(...) body
,其中...
将被映射到对列表。
{
本身就是一个函数。与(
不同,{
从不被解析器特别处理。
因此,当你的表达式中只有一个调用时,不需要{
,不是因为function
的语法被设计得很灵活,而是因为它不是function
语法的一部分。
我倾向于同意使用大括号保持一致性是一种很好的做法,当您想使用trace
例如不一致很烦人时。不过,它通常几乎没有什么后果,并且它不是由基数 R 强制执行的:
mean
# function (x, ...)
# UseMethod("mean")
# <bytecode: 0x000000000e146288>
# <environment: namespace:base>
body(mean)
# UseMethod("mean")
作为旁注,rlang
有一个很好的功能,能够获得一致的身体输出:
rlang::fn_body(mean)
# {
# UseMethod("mean")
# }