使用Magrittr从闭包构造函数会导致函数求值时出错

Max*_*ell 7 closures r magrittr

当我使用magrittr将x的值传递给下面的函数时,会导致函数无法使用.为什么会这样?我有版本magrittr_1.5.

library(magrittr)
f <- function(x) { function(y) { x + y } }

# Case 1 (works)
f.5 <- f(5)
f.5(6) # returns 11

# Case 2 (works)
f.5 <- f(5) 
6 %>% f.5 # returns 11

# Case 3 (fails)
f.5 <- 5 %>% f
6 %>% f.5 # Error in x + y (from 1) : 
          # non-numeric argument to binary operator 

# Case 4 (fails)
f.5 <- 5 %>% f
f.5(6); # Same error as case 3
Run Code Online (Sandbox Code Playgroud)

pic*_*ick 2

这是部分答案。x首先,如果您在内部匿名函数的调用环境中进行计算,则很容易使其工作,

library(magrittr)
f <- function(x) { x; function(y) x + y }
f.5 <- 5 %>% f
6 %>% f.5
# [1] 11
Run Code Online (Sandbox Code Playgroud)

要调查出了什么问题,看看x正在评估什么,

f <- function(x) {
    function(y) {
        print(sprintf("x: %s.", toString(x)))
        x + y
    }
}
## the failing case
fails <- 5 %>% f
6 %>% fails
# [1] "x: function (y) \n{\n    print(sprintf(\"x: %s\", toString(x)))\n    x + y\n}, TRUE"
Run Code Online (Sandbox Code Playgroud)

withVisible它指向调用on的结果f,这在调用函数 时发生freduce代码)。在函数体中pipe有一行,

body(magrittr:::pipe)[[2]][[3]][[10]]
# env[["freduce"]] <- freduce
Run Code Online (Sandbox Code Playgroud)

在哪里freduce可用(查看magrittr:::pipe完整上下文)。

如果将此行修改为函数中的实际代码freduce(即复制magrittr:::freduce),它似乎可以工作,

## Make a modified %>% operator
mypipe <- magrittr:::pipe

## Change that line
body(mypipe)[[2]][[3]][[10]] <- quote(
    env[["freduce"]] <-
        function(value, function_list) {
            k <- length(function_list)
            if (k == 1L) {
                result <- withVisible(function_list[[1L]](value))
                if (result[["visible"]])
                    result[["value"]]
                else
                    invisible(result[["value"]])
            } else {
                Recall(function_list[[1L]](value), function_list[-1L])
            }
        }
)

## Redefine
`%>%` <- mypipe()

## Test (now it works?!)
fails <- 5 %>% f
6 %>% fails
# [1] "x: 5"
# [1] 11
Run Code Online (Sandbox Code Playgroud)

所以,这是一个部分解决方案,因为我无法弄清楚为什么freduce以这种方式重新定义可以使其工作。