当前位置: 首页 > 知识库问答 >
问题:

是否有可能有'dput'返回的源代码,将在封闭的环境之外运行?

尹凌龙
2023-03-14

假设我有一个闭包addy(y),它返回一个函数,将y添加到它的输入中。

add_y <- function(y) {
  function(x) {
    x + y
  }
}
add_4 <- add_y(4)

因此,add_4的值是一个将4添加到其输入的函数。这很有效。我想使用dputadd_4的定义显示为

function(x) {
  x + 4
}

但这不是dput返回的结果。

add_y <- function(y) {
  function(x) {
    x + y
  }
}
add_4 <- add_y(4)
dput(add_4)
#> function (x) 
#> {
#>     x + y
#> }

有没有办法获得在封闭环境之外运行的源代码?

共有3个答案

廉展鹏
2023-03-14

您可以构建一个dput替换生成的代码,该代码创建类似于add_4的函数,但它不会偏离您想要的方式:

dput_with_env <- function(f) {
  fn <- deparse(f, control = c("keepNA", "keepInteger", 
                               "niceNames", "showAttributes"))
  env <- as.list(environment(f))
  cat("local({ f =\n")
  cat(fn, sep = "\n")
  cat("\nenvironment(f) <- list2env(\n")
  dput(env)
  cat(")\nf})")
}

add_y <- function(y) {
  function(x) {
    x + y
  }
}
add_4 <- add_y(4)

dput_with_env(add_4)
#> local({ f =
#> function (x) 
#> {
#>     x + y
#> }
#> 
#> environment(f) <- list2env(
#> list(y = 4)
#> )
#> f})

由reprex软件包(v2.0.1)于2021年12月24日创建

这假定add_4的环境非常简单,因此在评估代码时,其环境的父环境可以是适当的环境。我们可以试试:

newfn <- local({ f =
function (x) 
{
   x + y
}
environment(f) <- list2env(
list(y = 4)
)
f})

newfn
#> function (x) 
#> {
#>    x + y
#> }
#> <environment: 0x7f9a1b5e2318>
newfn(1)
#> [1] 5

由reprex软件包(v2.0.1)于2021年12月24日创建

屠振濂
2023-03-14

这是可行的,但它涉及到更改add\y的内容。

library(rlang)
library(magrittr)
library(stringr)

add_y <- function(y) {
  fn <- expr(function(x) {
    x+!!y
  })
  fn <- deparse(fn) %>% str_c(collapse = "")
  fn <- eval(parse(text = fn))
}

add_4 <- add_y(4)

dput(add_4)
#> function (x) 
#> {
#>     x + 4
#> }

由reprex软件包(v2.0.1)于2021年12月24日创建

南宫兴德
2023-03-14

如果您控制add_y,那么一种解决方法是将y的值直接注入内部函数的主体中,或者将其注入正式参数列表中。这消除了环境的使用,因此问题不再存在。这涉及到命名匿名内部函数,并且只有一个额外的行来执行注入,外加一行来返回结果。

# 1. inject into body
add_y2 <- function(y) {
  inner <- function(x) {
    x + y
  }
  body(inner) <- do.call("substitute", list(body(inner)))
  inner
}
# test
add_4 <- add_y2(4)
dput(add_4)
## function (x) 
## {
##     x + 4
## }

# 2. inject into formal arguments
add_y3 <- function(y) {
  inner <- function(x) {
    x + y
  }
  formals(inner)$y <- y
  inner
}
# test
add_4 <- add_y3(4)
dput(add_4)
## function (x, y = 4) 
## {
##     x + y
## }
 类似资料:
  • 根据Oracle文档 try with resources语句是声明一个或多个资源的try语句。资源是一个对象,在程序完成后必须关闭它。try with resources语句确保在语句末尾关闭每个资源。任何实现java的对象。AutoCloseable,其中包括实现java的所有对象。伊奥。可关闭,可用作资源 如果资源未实现AutoCloseable,则无法在try块中声明,必须在主体部分中声明

  • 我在路径“/test”中有一个无用的endpoint: 我这样测试: 但我得到一个断言错误: 预期状态代码 这发生在更多的代码中:400,500...除了200。 我用的是Spring靴。如果在运行测试时在endpoint方法中放置断点,则执行将停止,因此测试中的请求将正确完成。如果我将状态代码(在资源和测试中也是)更改为200,则测试通过。 到底发生了什么?

  • 问题内容: 现在我有了一些C源代码,我想在我的Java应用程序中使用它。我需要执行C源代码,并将结果返回到我的Java应用程序。与其将所有C源代码重写为Java,我如何在Java应用程序中重用C源代码? 问题答案: 看一下Java Native Interface 。 Java本机接口(JNI)是一种编程框架,它使Java虚拟机(JVM)中运行的Java代码能够被本机应用程序(特定于硬件和操作系统

  • 问题内容: 我看到有一条禁止的附庸制度。 在规则的描述中,它声明了一个add 。 但是,当我查看[MDN 函数docs时,“简单示例”显示了一个示例,其中没有任何说明这可能是性能问题的原因。 如eslint文档所建议的那样,是否存在实际的性能问题? 如果是这样,怎么办? 问题答案: 不,没有任何性能 问题 。这只是不必要的额外操作。执行可能需要更长的时间,但几乎不会引起注意。它类似于而不是整数。或

  • 问题内容: 我正在阅读面向对象的Javascript,并发现了闭包的概念。我不太明白为什么以及何时使用它。其他语言(例如Java)也有闭包吗?我基本上想了解了解闭包的概念如何帮助我改善编码。 问题答案: 闭包是具有绑定变量的第一类函数。 大致意味着: 您可以将闭包作为参数传递给其他函数 闭包存储创建时存在的词法作用域中某些变量的值 Java最初没有对闭包的语法支持(Java 8中引入了闭包),尽管

  • 问题内容: 我已经搜索了Wiki模块页面,但是找不到与virtualenv(python)或rvm类似的东西。 这里有人在自己的环境中分隔node.js吗?我真的不喜欢在系统范围内安装npm。 问题答案: 如果拥有系统范围的npm软件包是您的主要问题,那么可以考虑将非常酷的’bundle’命令与npm一起使用。这更接近于冻结宝石或在导轨中使用捆绑器,而不是rvm。 超级容易。只需创建一个packa