Оператор доллара как аргумент функции для sapply не работает как ожидалось

У меня есть следующий список

test_list=list(list(a=1,b=2),list(a=3,b=4))

и я хочу извлечь все элементы с именем элемента списка a.

Я могу сделать это через

sapply(test_list,`[[`,"a")

который дает мне правильный результат

#[1] 1 3

Когда я пробую то же самое с оператором Rs dollar $, я получаю NULL

sapply(test_list,`$`,"a")
#[[1]]
#NULL
#
#[[2]]
#NULL

Однако, если я использую его в одном элементе test_list, он работает как ожидалось

`$`(test_list[[1]],"a")
#[1] 1

Я пропустил что-то очевидное здесь?

Ответ 1

Из того, что я смог определить, это сочетание двух вещей.

Во-первых, второй элемент $ сопоставляется, но не оценивается, поэтому он не может быть переменной.

Во-вторых, когда аргументы передаются в функции, они назначаются соответствующим переменным в вызове функции. При передаче в sapply "a" назначается переменная и поэтому больше не будет работать с $. Мы видим это, выполняя запуск

sapply("a", print)
[1] "a"
  a 
"a"

Это может привести к особым результатам, подобным этому

sapply(test_list, function(x, a) {`$`(x, a)})
[1] 1 3

Если несмотря на то, что a является переменной (которая еще не была назначена) $ соответствует ей именам элементов в списке.

Ответ 2

оценка против none

[[ оценивает свой аргумент, а $ - нет. L[[a]] получает компонент L, имя которого хранится в переменной a. $ просто передает имя аргумента как строку символов, поэтому L$a находит "a" компонент L. a не рассматривается как переменная, содержащая имя компонента - только символьная строка.

Ниже L[[b]] возвращает компонент L с именем "a", потому что переменная b имеет значение "a", тогда как L$b возвращает компонент L с именем "b", потому что с этим синтаксисом 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

Теперь, когда мы понимаем ключевое различие bewteen $и [[чтобы посмотреть, что происходит с sapply, рассмотрим этот пример. Мы сделали каждый элемент test_list в объект "foo" и определили наши собственные методы $.foo и [[.foo, которые просто показывают, что R передает метод через аргумент name:

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")    
## [1] "a"
## [1] "a"

Что происходит в первом случае, так это то, что sapply вызывает whatever$..., а ... не оценивается, поэтому он будет искать компонент списка, который буквально называется "...", и, конечно же, существует нет такой компоненты, поэтому whatever$... равно NULL, следовательно, NULL, показанные на выходе в вопросе. Во втором случае whatever[[[...]] оценивает whatever[["a"]], следовательно, наблюдаемый результат.