什么是对象?

What is an object?

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

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

这个错误暗示 function(x) x * x 是一个对象,但不是语言对象。然而,names() 的文档说它允许“一个 R 对象”作为其输入,这与这个前提相矛盾。此外,the language definition 说“In R functions are objects”,这进一步混淆了问题。最后,is.object(function(x) x * x) returns FALSE,但我认为这是出于 class 的原因。

我的问题是:什么是对象以及为什么 names()function(x) x * x 视为不是一个对象?

正在查看 R source code (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}},
...

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

这在 coerce.cdo_is 的定义中得到证实:

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

对象有以下方法:

/* 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}},

指向基础 R 文档:

R possesses a simple generic function mechanism which can be used for an object-oriented style of programming. Method dispatch takes place based on the class(es) of the first argument to the generic function or of the object supplied as an argument to UseMethod or NextMethod.

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

is.object - Is an object internally classed? It returns TRUE if the object x has the R internal OBJECT bit set, and FALSE otherwise. The OBJECT bit is set when a "class" attribute is added and removed when that attribute is removed, so this is a very efficient way to check if an object has a class attribute. (S4 objects always should.)

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

与普通语言中的对象相比,这是非常严格的。 不确定 R 文档在谈到对象时总是表示 objects(50)

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

您遇到的错误不是由于 function object 的性质,而是 names<- 的参数是“匿名”[=50] =] 而不是链接到符号的。考虑一下:

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

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

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

同样的错误。

这当然有效:

a<-1:10
names(a)<-letters[1:10]

进入你的例子:

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

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

"names<-"(function(x) x*x, "square")
# Error: names() applied to a non-vector

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

‘names’ is a generic accessor function, and ‘names<-’ is a generic replacement function. The default methods get and set the ‘"names"’ attribute of a vector (including a list) or pairlist.

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

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

语法错误和措辞不当的错误消息几乎无法说明语言中对象的状态。这是一条红鲱鱼。