评估 vs. 不评估
[[
会评估其参数,而 $
则不会。 L[[a]]
获取变量 a
中保存的名称对应的 L
组件。 $
只将参数名本身作为字符串传递,所以 L$a
找到 L
的 "a"
组件。此时,a
不被视为保存组件名称的变量,只是一个字符串。
下面,因为变量 b
的值为 "a"
,所以 L[[b]]
返回名为 "a"
的 L
组件,而 L$b
返回名为 "b"
的 L
组件,因为该语法中的 b
不被视为变量,而是被视为传递的字符串本身。
L <- list(a = 1, b = 2)
b <- "a"
L[[b]] # same as L[["a"]] since b holds a
## [1] 1
L$b # same as L[["b"]] since b is regarded as a character string to be passed
## [1] 2
sapply
现在我们理解了$和[[之间的主要区别,为了看清sapply
的运行情况,请考虑以下示例。我们将test_list
的每个元素变成"foo"
对象,并定义了自己的$.foo
和[[.foo
方法,这些方法仅通过name
参数显示R传递给方法的内容:
foo_list <- test_list
class(foo_list[[1]]) <- class(foo_list[[2]]) <- "foo"
"$.foo" <- "[[.foo" <- function(x, name) print(name)
result <- sapply(foo_list, "$", "a")
result2 <- sapply(foo_list, "[[", "a")
在第一种情况下发生的是sapply
调用了whatever$...
,但...
没有被评估,所以它将查找一个列表组件,该组件实际上命名为"..."
,当然,没有这样的组件,因此whatever$...
是NULL,因此在问题输出中显示了NULL。在第二种情况下,whatever[[[...]]]
评估为whatever[["a"]]
,因此观察到了结果。
x="a";"$"(test_list[[1]],x);
给出了一个不正确的结果。 - cryo111"$"(test_list[[1]],a)
会给出1
,尽管没有定义对象a
。 - cryo111