代码之家  ›  专栏  ›  技术社区  ›  xiaodai

不使用'function'关键字定义匿名函数

r
  •  7
  • xiaodai  · 技术社区  · 7 年前

    我可以定义并使用一个匿名函数,然后像这样调用它

    x <- 1:3
    sapply(x, function(x) x)
    

    有时候我觉得 function 这样太冗长了。有没有其他方法来定义匿名函数?

    purrr package ,可以这样定义一个匿名函数

    map(x, ~.x)
    

    但这只适用于 咕噜声 上下文

    5 回复  |  直到 4 年前
        1
  •  7
  •   Spacedman    7 年前

    你能说得少一点吗?你需要某种指标来证明这是一个函数,用某种方式来表示参数,用某种方式来表示计算。唯一让它“冗长”的是“函数”有八个字母。如果您不希望这样,那么定义您的函数 外部 申请,然后你得到 sapply(x, foo) 它简洁、描述性强、易于理解,无需借助外部依赖(PURRR)或非标准评估。

        2
  •  7
  •   G. Grothendieck    7 年前

    1) gsubfn::fn 这个 gsubfn package 支持定义函数的公式表示法,与问题中提到的purrr不同,purrr只适用于purrr函数,它适用于几乎任何函数。

    如果一个匿名函数被传递给另一个函数,在本例中,匿名函数被传递给 sapply ,然后是前言 聪明的 具有 fn$ 并使用args~body形式的公式表示法。如果缺少arg,则假定主体中的自由变量是主体中遇到的顺序的参数,因此在下面的第一个示例中 z 假设为单一参数。

    library(gsubfn)
    
    x <- 1:3
    fn$sapply(x, ~ z)
    ## [1] 1 2 3
    
    # same - specify arg
    fn$sapply(x, z ~ z)
    ## [1] 1 2 3
    
    # same - can use any variable name we like
    fn$sapply(x, ~ x)
    ## [1] 1 2 3
    
    # same
    sapply(x, function(z) z)
    ## [1] 1 2 3
    

    匿名函数可以有任意数量的参数。以下都是相同的:

    fn$sapply(x, ~ u + 2 * v, v = 10)
    ## [1] 21 22 23
    
    # same
    fn$sapply(x, u + v ~ u + 2 * v, v = 10)
    ## [1] 21 22 23
    
    # same
    sapply(x, function(u, v) u + 2 * v, v = 10)
    ## [1] 21 22 23
    

    2) 马格里特

    这个 magrittr package 支持定义单参数函数的管道表示法。论点必须是圆点。

    library(magrittr)
    
    x <- 1:3
    sapply(x, . %>% {.})
    ## [1] 1 2 3
    
    # same
    sapply(x, function(x) x)
    ## [1] 1 2 3
    
    # same
    x %>% sapply(. %>% {.})
    ## [1] 1 2 3
    

    3) 拉姆达。R 这个 lambda.r package 允许定义 命名的 函数使用 %as% .这里我们定义一个名为 fun .

    library(lambda.r)
    
    x <- 1:3
    fun(x) %as% x
    sapply(x, fun)
    ## [1] 1 2 3
    
    # same
    fun <- function(x) x
    sapply(x, fun)
    ## [1] 1 2 3
    
        3
  •  2
  •   Nicolas2    7 年前

    “wrapr”包提供了几种缩写匿名函数的方法。在LINUX平台上(取决于操作系统和语言环境,允许lambda字符成为可用于命名符号的“字母”),可以执行以下操作:

    library(wrapr)
    λ <- lambda
    sapply(1:10,λ(x,x^2))
    #[1]   1   4   9  16  25  36  49  64  81 100
    
    λ(x,y,x*y)(6,7)
    #[1] 42
    
        4
  •  2
  •   moodymudskipper    7 年前
    • 这个 pryr::f 函数允许非常紧凑的函数定义,它可以从您提供给它的表达式中猜测函数的参数,它适用于简单的调用。
    • purrr 使用 purrr::as_mapper ,其本身称为 rlang::as_function ,所以你也可以称之为这些,但它并没有那么冗长。
    • I wrote a package called lambda 这使得公式符号与base R(或任何具有较小设置的软件包)兼容,它正在进行中,但已经完全可用。仅供互动使用,不要用它编程。

    例如:

    F

    aggregate(. ~ Species, iris, pryr::f(mean(range(.))))
    #      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
    # 1     setosa         5.05        3.35         1.45        0.35
    # 2 versicolor         5.95        2.70         4.05        1.40
    # 3  virginica         6.40        3.00         5.70        1.95
    

    as_函数

    aggregate(. ~ Species, iris, rlang::as_function(~mean(range(.))))
    #      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
    # 1     setosa         5.05        3.35         1.45        0.35
    # 2 versicolor         5.95        2.70         4.05        1.40
    # 3  virginica         6.40        3.00         5.70        1.95
    

    您可以将其分配给一个简短的变量,以实现紧凑的语法:

    .. <- rlang::as_function
    aggregate(. ~ Species, iris, ..(~mean(range(.))))
    

    作为地图绘制者

    aggregate(. ~ Species, iris, purrr::as_mapper(~mean(range(.))))
    #      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
    # 1     setosa         5.05        3.35         1.45        0.35
    # 2 versicolor         5.95        2.70         4.05        1.40
    # 3  virginica         6.40        3.00         5.70        1.95
    

    拉姆达

    # devtools::install_github("moodymudskipper/lambda")
    library(lambda)
    attach_lambda()
    aggregate(. ~ Species, iris, ~mean(range(.)))
    #      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
    # 1     setosa         5.05        3.35         1.45        0.35
    # 2 versicolor         5.95        2.70         4.05        1.40
    # 3  virginica         6.40        3.00         5.70        1.95
    

    其他功能包括 base::Negate , base::vectorize , purrr::partial , purrr::compose ... 有时可以帮助使代码更紧凑。

        5
  •  1
  •   Aaron Hayman    7 年前

    我相信任何一个明智的R程序员都应该对以下内容感到非常生气,但为了好玩,这似乎是可行的,并且省去了调用一个6个字母长的函数的麻烦

    s=function(x,f)
    {
        eval(parse(text = paste('y <- function(x)',deparse(substitute(f)),collapse='')))
        sapply(x,y)
    }
    

    所以现在 s 是用来代替 sapply .

    s(1:3,x*2)
    ## [1] 2 4 6
    

    x必须用作函数的单参数,这很可能是个大问题。

        6
  •  1
  •   tdy TheChimp    4 年前

    R4.1.0中的新功能

    反斜杠现在可以用作创建匿名函数的简写。例如 \(x) x + 1 现在被解析为 function(x) x + 1 .

    sapply(1:3, \(x) x + 1)
    # [1] 2 3 4