Purrr与[[<-]]。

问题描述 投票:1回答:1

谁能给我解释一下,为什么使用purrr.Purrr.会出错,但使用lapply同样的调用似乎可以。

map(list(list(a=1, b=2, c=3), list(a=1, b=2, c=3)), `[[<-`, "b", 1)

但同样的调用lapply似乎也可以。

我的印象是 [[<- 只是一个函数调用,所以希望purrr和lapply在这里做同样的事情。

purrr
1个回答
4
投票

问题在于 purrr::as_mapper(),其中 map() 引擎盖下的电话。考虑一下两者的区别。

x <- list( a=1, b=2, c=3 )

`[[<-`( x, "b", 1 )                    # This is what lapply() calls
                                       # x is unchanged, returns modified list


purrr::as_mapper(`[[<-`)( x, "b", 1 )  # This is what map() calls
                                       # x is modified in-place, returns value 1

第二个函数调用就像你输入了下面的赋值表达式一样:

(x[["b"]] <- 1)          
# [1] 1

当函数被传给下面的函数时,一定会引起问题 map() 的内部结构。有趣的是,用一个 ~ lambda 工作,但返回 "错误 "的结果。

y <- list(list(a=1, b=2, c=3), list(a=1, b=2, c=3))

purrr::map( y, ~purrr::as_mapper(`[[<-`)(.x, "b", 1) )
# [[1]]
# [1] 1

# [[2]]
# [1] 1

purrr::map( y, purrr::as_mapper(`[[<-`), "b", 1 )
# Error in list(a = 1, b = 2, c = 3)[["b"]] <- 1 : 
#   target of assignment expands to non-language object

正确的 purrr 相当于你的 lapply() 的例子会是这样的。

r1 <- lapply(y, `[[<-`, "b", 1)
r2 <- purrr::map(y, purrr::modify_at, "b", ~1)
r3 <- purrr::map(y, ~`[[<-`(.x, "b", 1))

identical( r1, r2 )               # TRUE
identical( r1, r3 )               # TRUE

在上面的例子中: modify_at() 返回修改后的列表,就像 [[<-(...) 的,而tilde ~ 是需要的,因为 modify_at() 期待一个函数。另一种方法是将 `[[<-` 变成 ~ 兰姆达:

© www.soinside.com 2019 - 2024. All rights reserved.