r - R 中的函数运算符和函数包装

标签 r functional-programming dplyr

Hadley 的“Advanced R”让我们简要了解函数式编程和“函数运算符”的可能应用。然而,我担心的是我要么不完全理解这些如何简化代码,要么不情愿地通过使用其他解决方案来遵循一些不好的做法。
我没有创建期望输入是函数的运算符,而是创建了一个包装器,它将一个表达式作为其参数,并返回一个完整的输出(而不是一个仍然需要调用的函数)。见示例:

# function operator
delay_by <- function(delay, f) {
  function(...) {
    Sys.sleep(delay)
    f(...)
  }
}

# simple wrapper
delay_by2 <- function(expr, delay) { 
  Sys.sleep(delay)
  eval(expr)
}

delay_by(1, sqrt)(2)
delay_by2(sqrt(2), 1)

operator <- delay_by(1, sqrt)
wrapper <- function(x) delay_by2(sqrt(x), 1)

operator(2)
wrapper(2)
这种方法仍然允许输入泛函(sapply 等)并应用内存。此外,这支持管道 %>% .
lapply(1:10, function(x) sqrt(x) %>% delay_by2(1))
此解决方案的潜在缺点是它没有创建持久执行环境来存储维护函数状态的变量,但可以使用 <<- new.env() 显式创建这些变量。 .
有什么理由让我认为我的方法低劣吗?我试图避免不必要的嵌套。

最佳答案

  • 一个重要的软件工程方面是功能很容易
    测试和打包,表达式不多。所以如果你使用一个
    函数方法可以编写单元测试,并将其放入包中。
    使用 eval 方法,您仅限于自己的 REPL 测试。显然我们都应该做“测试驱动开发”,至少在我们的生产代码上,什么都不应该出去
    没有一组覆盖尽可能多的代码的单元测试
    经济上可行。这让人们的生活变得更轻松
    (包括你)谁可能有一天需要做出改变。
  • 另请注意,可能存在可以在函数范围内完成的编译器优化,但不能在表达式上完成。那会是真的
    在其他语言中,但我不太了解 R 的编译器
    可以对此发表任何看法。
  • 我想到的另一点是 eval 路线并不是真正可扩展的,即仅适用于高达 a
    一定的复杂性。另一方面,使用函数可以让您
    逻辑增长到任何实际规模。
  • 最后,eval作为一个构造体是一个非常强大的构造体,但它会给你带来麻烦,有点像使用高功率激光
    Papercut 。由于它通常易于实现,因此它存在于许多
    语言,网上有很多关于它为什么危险的文章——你应该看看它们。所以像那个高功率激光,你不应该真的得到
    习惯使用它,除非有必要。
  • 关于r - R 中的函数运算符和函数包装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42054590/

    相关文章:

    r - 存储来自 ggplot2 的直方图以供稍后检索

    再现 Fisher 线性判别图

    javascript - 在 JavaScript 中使用 transduce 进行优化 - Transducers 和 Ramda

    algorithm - 实现一个带有前缀树的基本搜索引擎

    r - 无法在 dplyr.spark.hive 包中创建由 SparkSQL 支持的 dplyr src

    r - 使用 R 删除列表中出现在一个元素及其自身之前的元素

    r - 如何使用 ggplot2 绘制 FDA 对象?

    C++ std::function 返回意外值

    r - 逐步完成具有中间结果的管道

    r - 在 dplyr::coalesce 中传递一个字符串作为变量名