什么是对象?

J. *_*ini 3 attributes r object

考虑以下愚蠢的输入和输出:

> names(function(x) x*x)<-"square"
Error in names(function(x) x * x) <- "square" : 
  target of assignment expands to non-language object
Run Code Online (Sandbox Code Playgroud)

隐含地,这个错误表明它function(x) x * x是一个对象,但是一个非语言对象。然而,文档names()说它允许“一个 R 对象”作为它的输入,这与这个前提相矛盾。此外,语言定义说“在 R 中函数是对象”,这进一步混淆了问题。最后,is.object(function(x) x * x)返回FALSE,但我认为这是出于课堂原因。

我的问题是:什么是对象,为什么names()将其function(x) x * x视为不是对象?

nic*_*ola 6

您得到的错误不是由于function对象的性质,而是由于参数names<-是“匿名”对象而不是已链接到符号的对象。考虑一下:

names(1:10)<-letters[1:10]
#Error in names(1:10) <- letters[1:10] : 
#  target of assignment expands to non-language object 
Run Code Online (Sandbox Code Playgroud)

相同的输出。在错误中,non-language看起来像是说“不是符号”的一种非常复杂的方式。但是,您有错误是很合乎逻辑的,因为您正在调用替换函数并且您要求替换其内容的符号不存在。从根本上讲,它与<-运算符有关,它期望赋值的左侧是符号(语言对象)而不是“标准”对象:

1:10<-setNames(1:10,letters[1:10])
#Error in 1:10 <- setNames(1:10, letters[1:10]) : 
#  target of assignment expands to non-language object
Run Code Online (Sandbox Code Playgroud)

又是同样的错误。

这当然有效:

a<-1:10
names(a)<-letters[1:10]
Run Code Online (Sandbox Code Playgroud)

进入你的例子:

f<-function(x) x*x
names(f)<-"square"
# Error in names(f) <- "square" : names() applied to a non-vector
Run Code Online (Sandbox Code Playgroud)

如果names<-使用“匿名”函数显式调用,则会出现上述错误:

"names<-"(function(x) x*x, "square")
# Error: names() applied to a non-vector
Run Code Online (Sandbox Code Playgroud)

现在错误是由于这样一个事实names<-,虽然是泛型,但没有函数的方法。这记录在?names, 详细信息部分:

'names' 是通用访问器函数,而 'names<-' 是通用替换函数。默认方法获取和设置向量(包括列表)或配对列表的“名称”属性。

我只是针对主要问题添加了几行:“什么是对象”。在 R 中,一切都是对象。该is.object函数有一个误导性的名称,更好的名称应该是is.internalobjectbitset. 该文档非常清楚。标题说:“对象是'内部分类'吗?” 而不是“变量是对象吗?”;在参数部分,因为x它说: x: object to be tested,如果你想首先测试是否x是一个对象,这很奇怪。它还指定主要用于内部使用,而不是作为定义什么是对象的方式(这将是一个愚蠢的函数,因为在 R 中一切都是对象)。

在评论之后,我要补充一点,总而言之,文档没有说明,虽然您可以应用于names任何 R 对象,但您不能分配names给某些类型。在我看来,这是一个非常小的问题,因为names它不仅仅是一个普通的属性,而且与语言的某些属性特别是子集非常相关。只有可以是子集的对象才能有名称。函数对象并不意味着是子集,因此 R 阻止分配一个基本上没有用的名称属性。


Wal*_*ldi 5

查看R 源代码 ( names.c)

{"is.null",       do_is,        NILSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.logical",    do_is,        LGLSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.integer",    do_is,        INTSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.double",     do_is,        REALSXP,1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.complex",    do_is,        CPLXSXP,1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.character",  do_is,        STRSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.symbol",     do_is,        SYMSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.name",       do_is,        SYMSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.environment",do_is,        ENVSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.list",       do_is,        VECSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.pairlist",   do_is,        LISTSXP,1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.expression", do_is,        EXPRSXP,1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.raw",        do_is,        RAWSXP, 1,  1,  {PP_FUNCALL, PREC_FN,   0}},

{"is.object",     do_is,        50,     1,  1,  {PP_FUNCALL, PREC_FN,   0}},

{"isS4",          do_is,        51,     1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.numeric",    do_is,        100,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.matrix",     do_is,        101,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.array",      do_is,        102,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.atomic",     do_is,        200,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.recursive",  do_is,        201,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.call",       do_is,        300,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
{"is.language",   do_is,        301,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},

{"is.function",   do_is,        302,    1,  1,  {PP_FUNCALL, PREC_FN,   0}},
...
Run Code Online (Sandbox Code Playgroud)

表明objects(50) 是一个特定类型,不同于function(302) 或其他类型 ( numeric,matrix ,...)

这证实了的定义do_iscoerce.c

    case 50:        /* is.object */
    LOGICAL0(ans)[0] = OBJECT(CAR(args));
    break;
Run Code Online (Sandbox Code Playgroud)

对象有以下方法:

/* Objects */
{"inherits",    do_inherits,    0,  11, 3,  {PP_FUNCALL, PREC_FN,   0}},
{"UseMethod",   do_usemethod,   0,     200, -1, {PP_FUNCALL, PREC_FN,   0}},
{"NextMethod",  do_nextmethod,  0,     210, -1, {PP_FUNCALL, PREC_FN,   0}},
{"standardGeneric",do_standardGeneric,0, 201,   -1, {PP_FUNCALL, PREC_FN,   0}},
Run Code Online (Sandbox Code Playgroud)

其中指向基础 R 文档:

R 拥有简单的通用函数机制,可用于面向对象的编程风格。方法分派基于泛型函数的第一个参数的类或作为 UseMethod 或 NextMethod 的参数提供的对象的类进行。

这表明由 检测到的类型 50 的对象is.object只是 S3 类或 S4 类,并由is.object文档确认:

is.object- 对象是内部分类的吗?如果对象 x 设置了 R 内部 OBJECT 位,则返回 TRUE,否则返回 FALSE。OBJECT 位在“class”属性被添加和移除时被设置,因此这是一种检查对象是否具有类属性的非常有效的方法。(S4 对象总是应该的。)

简而言之:内部对象具有class属性集

与通用语言中的对象相比,这是相当严格的。不确定 R 文档objects(50)在谈论对象时总是意味着什么。

关于names(function())错误,请参阅@nicola 的澄清。