为什么函数有时只是 R 中的第一类变量?从内置数据结构中使用它们会导致“错误:尝试应用非函数”

Why are functions only sometimes first class variables in R? Using them from built-in data structures causes "Error: attempt to apply non-function"

提问人:David 提问时间:11/5/2022 最后编辑:David 更新时间:11/5/2022 访问量:34

问:

我正在尝试了解第一类函数在 R 中是如何工作的。我明白函数在R语言中是第一类的,但是在应用这种理解时,我感到非常失望。当函数保存到列表中时,无论是普通列表、向量还是字典样式列表或向量,它都不再可调用,从而导致以下错误:

Error: attempt to apply non-function

例如:

print_func <- function() {
  print('hi')
}
print_func()
[1] "hi"

my_list = list(print_func)
my_list[0]()
Error: attempt to apply non-function

my_vector = c(print_func)
my_vector[0]()
Error: attempt to apply non-function

my_map <- c("a" = print_func)
my_map["a"]()
Error: attempt to apply non-function

那么为什么会这样呢?实际上并非在所有情况下都将函数视为第一类成员,还是有其他原因发生这种情况?

我看到 R 向量也会对嵌套数组做意想不到的事情(对我来说 - 也许不适合有经验的 R 用户):

nested_vector <- c("a" = c("b" = 1))
nested_vector["a"]
<NA> 
  NA
nested_vector["a.b"]
a.b 
  1

在这里,“a.b”可能指的是键“a”下键“b”的子成员,这对我来说是有道理的。但显然,当尝试将上层键称为“a”时,这种逻辑就消失了。

r 数据结构 第一类函数

评论

1赞 Limey 11/5/2022
一个直接的评论:您应该使用 ,而不是 访问列表元素。R 中的列表和向量是基于 1 的,而不是从 0 开始的。[[[
0赞 David 11/5/2022
@Limey 谢谢,我应该尝试索引为 1 的列表/向量示例。虽然我只是用索引 1 测试了它们,但它们得到了完全相同的错误。我发现与 Python 相比,在 R 中调试也非常困难!编辑:刮一下,它适用于双括号语法。

答:

1赞 B. Christian Kamgang 11/5/2022 #1

R 是从 1 开始的;因此,您使用索引 1(而不是像 Python 中的 0)来引用向量的第一个元素。

有两种方法可以访问列表元素:

  • 在保留列表的同时访问列表元素(返回包含所需元素的列表)
  • 从列表中拉出元素

在第一种情况下,子集是使用一对括号 () 完成的,您将始终得到一个列表。请注意,这与 python 不同,在 python 中,只有当您选择多个元素 (; return 而不是像 R 这样的单元素列表,而返回一个列表)。[]lst = [fun1, fun2]lst[0]fun1lst[0:2]

在第二种方法中,子集是使用双括号 () 完成的。你基本上把一个元素完全从列表中拉出来;更像是在 Python 中将一个元素从列表中子集出来。[[]]

print_func <- function() {
  print('hi')
}
print_func()


my_list = list(print_func)

mode(my_list[1])      # return a list (not a function); so, it's not callable
[1] "list"
mode(my_list[[1]])    # return a function; so, it's callable
[1] "function"
my_list[1]()          # error
my_list[[1]]()        # works
[1] "hi"
# 
my_vector = c(print_func)
mode(my_vector)         # a list, so, not callable
[1] "list"
my_vector[1]()          # error because it returns a list and not a function
my_vector[[1]]()        # works
[1] "hi"

当使用名称进行子集时,适用单括号和双括号对的相同逻辑

my_map <- c("a" = print_func)
mode(my_map)            # list, so, not callable
[1] "list"
my_map["a"]()           # error
my_map[["a"]]()         # works
[1] "hi"