【问题标题】:Using partial within map在地图内使用部分
【发布时间】:2017-03-10 20:19:46
【问题描述】:

我遇到了一个有趣的问题。我有一个三个变量的函数,假设(为了简单和透明)它是这样的:

my_fun <- function(a, b, c) paste(a, b, c, sep = '-')

我想为ab 的几种组合创建多个函数,只有参数c。我正在使用函数map2partial(都来自包purrr)。

require(purrr)
funs <- map2(letters[1:5], LETTERS[1:5], partial, ...f = my_fun)

我希望函数列表中的每个函数产生不同的输出,但事实并非如此。

funs[[1]]('hi')    # [1] "e-E-hi"
funs[[3]]('hi')    # [1] "e-E-hi"
funs[[5]]('hi')    # [1] "e-E-hi"

我能够为我的问题创建不同的解决方案,所以我的问题不是“如何去做”。我对它为什么这样做很感兴趣。


另一个使用基数mapply的例子:

mapply(partial, letters[1:5], LETTERS[1:5], MoreArgs = list(...f = my_fun))[[1]]('hi')
# [1] "e-E-hi"

【问题讨论】:

  • 它是一个懒惰的评估事情......添加.lazy=FALSE 解决了它,但为什么我不清楚。

标签: r purrr


【解决方案1】:

问题源于partial 使用惰性求值,这在map2 中意味着它存储.x.y 而不是aA。幸运的是,有一个函数参数,我们可以使用:

funs <- map2(letters[1:5], LETTERS[1:5], partial, ...f = my_fun, .lazy = FALSE)

funs[[1]]('hi')
# [1] "a-A-hi"

如果您查看您的版本,我们会看到:

funs[[1]]

# function (...) 
# my_fun(.x[[i]], .y[[i]], ...)
# <environment: 0x00000000201d9598>

其他 4 个也一样。

现在,如果我们查看那个环境,我们可以看到:

ls(envir = environment(funs[[1]]))
# [1] "i"

所以那里存储了一个对象i,它将确定我们得到哪个.x.y,其值为:

get('i', environment(funs[[1]]))
# [1] 5

另请注意,您的参数也存储在那里,但由于它们以 . 开头而被隐藏:

ls(envir =     environment(funs[[1]]), all.names = TRUE)
# [1] "..." ".f"  ".x"  ".y"  "i" 
get('.x', envir = environment(funs[[1]]))
# [1] "a" "b" "c" "d" "e"

所以对于所有这些,我们得到相同的结果。具体来说,执行的调用最终是:

my_fun(letters[1:5][[5]], LETTERS[1:5][[5]], 'hi')

惰性求值在这里不太好用,并使用map2 中存储的内部循环计数器。

【讨论】:

  • 感谢您的澄清。我没有意识到map 中的参数带有点(因此隐藏)。我在单个函数的环境中只看到了变量i
  • 确实,我已经为答案添加了一些说明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
相关资源
最近更新 更多