在R中的function(x):如何在不定义函数的情况下编写“函数”?

11

我遇到过这个概念几次,但不知道它的名称,因此无法通过谷歌了解更多信息。基本上,当查看其他人编写的函数或甚至简单的命令时,我经常会看到类似于这样的东西:

apply(dataset, 1:2, function(x) 10 * x)

在这种情况下,我能够推断出这个“假函数”function(x)以某种方式将数据集的每个元素乘以10。这似乎是一个有用的功能,但我仍然不确定何时或如何使用它。它真的是一个函数吗?还是只能在apply函数族中使用?这个东西有名字吗?


6
这叫做匿名函数。这样可以帮助你更好地进行搜索。 - joran
3个回答

12
那些被称为“匿名函数”,它们是真正的函数对象,只是在使用之前没有被分配给任何符号。
以下是来自R语言文档的相关内容:
“通常情况下,函数会被分配到符号上,但并非必须如此。函数调用返回的值是一个函数。如果没有给它赋予名称,则称为匿名函数。匿名函数最常用作其他函数(如apply系列或outer)的参数。”
尽管它们通常在*apply()函数中使用,但它们不必如此,例如:
(function(x,y){x*y + x/y})(2,5)
# [1] 10.4

7

R 4.1.0版本开始,现在可以本地使用\(x) {}代替function(x) {}来表示匿名函数。

应用代码可以编写为

dataset |>
    apply(1:2, \(x) {10 * x})

不仅适用于匿名函数。 - January

5
你是在说一个匿名函数(lambda)吗?你可以在你的~/.Rprofile文件中加入类似这样的内容:
`{` <- function(...)
  base::`{`(
    if (length(sys.calls()) >= 4 &&
        identical(as.character(sys.call()[[1]]), "{") &&
        identical(as.character(sys.call(-4)[[1]]), "{"))
      base::`{`(fn <- new('function'),
        formals(fn) <- alist(x=), body(fn) <- sys.call(), fn)
    else eval.parent(substitute(base::`{`(...)))
  )

那么你可以做这样的事情:

然后你可以做如下操作:

sapply(1:10, {{x + 5}})
# [1]  6  7  8  9 10 11 12 13 14 15

这更接近于像Ruby或Coffeescript这样的语言,它们不需要调用关键字来创建lambda函数(在那里它们使用->,但这已经在R中使用了,所以我使用了双大括号)。我刚想到这个,如果有错误请告诉我。


6
这可能对问题提出者没有帮助,但这是一个有趣的想法。我个人比较偏爱重载->操作符。 (参考链接:https://gist.github.com/klmr/25dc765211c59bb749b0) - Konrad Rudolph
我猜你可以把 %>% 转换成 base::\<-``? - Robert Krzyzanowski
1
这是一个有趣的想法,但我建议在重新定义这样一个基本的 R 符号时要小心。例如,在您重新定义 { 之前和之后,我的计算机上 system.time(replicate(1e6, {1+1})) 的运行时间从3.7秒变为37.1秒。 - Josh O'Brien
2
@KonradRudolph 实际上,您可以与 <- 一起重载 (,以创建与 Coffeescript 中完全相同的 lambda。 - Robert Krzyzanowski
4
是的,总有一天我希望能够理解这里所说的四分之一以上的内容:) 听起来很有趣... - HFBrowning
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接