Требуется ли функция () - функция в R "not" в фигурных скобках? - PullRequest
5 голосов
/ 31 мая 2019

Я недавно столкнулся с этим примером в моем учебнике по R:

sapply(list(runif (10), runif (10)), 
   function(x) c(min = min(x), mean = mean(x), max = max(x))

У меня сложилось впечатление, что в функции function () вы сначала должны были перечислить свои аргументы в скобкаха затем действия, выполняемые функцией внутри фигурных скобок.

В этом примере в фигурных скобках «нет», и, похоже, код работает в любом случае, как это может быть?

Ответы [ 2 ]

3 голосов
/ 31 мая 2019

Это единственное утверждение, для которого нет необходимости в скобках

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
0 голосов
/ 03 июня 2019

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, как можем с другими: Как мне вызвать функцию `function`?

Синтаксис, используемый для fun1: function(...) body, где ... будет отображен в список pairlist.

{ сама по себе является функцией. В отличие от (, { никогда не обрабатывается парсером.

Поэтому, когда в вашем выражении содержится один вызов, { не требуется, не потому, что синтаксис 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")
# }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...