R中存在的所有“物体是一个物体”的真正含义是什么?

时间:2015-12-19 23:04:57

标签: r

我看到了:

  

“要理解R中的计算,两个口号是有帮助的:

     

•存在的一切都是一个对象     •发生的一切都是函数调用。“

     

- John Chambers

但我刚发现:

a <- 2
is.object(a)
# FALSE

实际上,如果变量是纯基类型,则结果是.object()将为FALSE。所以它不应该是一个对象。

那么“R中存在的所有东西是一个物体”的真正含义是什么?

3 个答案:

答案 0 :(得分:23)

函数is.object似乎只是查看对象是否具有“class”属性。所以它与口号中的含义不同。

例如:

x <- 1
attributes(x) # it does not have a class attribute
NULL
is.object(x)
[1] FALSE
class(x) <- "my_class"
attributes(x) # now it has a class attribute
$class
[1] "my_class"
is.object(x)
[1] TRUE

现在,试着回答你真正的问题,关于口号,这就是我要说的。 R中存在的所有内容都是一个对象,因为它是一种可以被操纵的数据结构。我认为通过函数和表达式可以更好地理解这一点,通常不会将其视为数据。

引用钱伯斯(2008)的话:

  

R中的中心计算是一个函数调用,由   函数对象本身和作为提供的对象   参数。在函数式编程模型中,定义了结果   通过另一个对象,调用的值。因此传统的座右铭   S语言:一切都是对象 - 参数,价值,   实际上是函数和调用本身:所有这些都是定义的   作为对象。将对象视为各种数据的集合。包含的数据和数据的组织方式取决于生成对象的类。

以此表达式为例mean(rnorm(100), trim = 0.9)。在评估之前,它与其他任何东西非常相似。因此,您可以像使用列表一样更改其元素。例如:

call <- substitute(mean(rnorm(100), trim = 0.9))
call[[2]] <- substitute(rt(100,2 ))
call
mean(rt(100, 2), trim = 0.9)

或采取一项功能,例如rnorm

rnorm
function (n, mean = 0, sd = 1) 
.Call(C_rnorm, n, mean, sd)
<environment: namespace:stats>

您可以像简单对象一样更改其默认参数,例如列表:

formals(rnorm)[2] <- 100
rnorm
function (n, mean = 100, sd = 1) 
.Call(C_rnorm, n, mean, sd)
<environment: namespace:stats>

再从Chambers(2008)那里再来一次:

  

关键概念是评估表达本身   对象;在S语言的传统座右铭中,一切都是   宾语。评估包括将对象表示为   表达式并返回作为其值的对象   表达

回到我们的调用示例,call是一个代表另一个对象的对象。在评估时,它变成另一个对象,在这种情况下是带有一个数字的数字向量:-0.008138572。

set.seed(1)
eval(call)
[1] -0.008138572

这将把我们带到第二个口号,你没有提到,但通常与第一个口号相关:“发生的一切都是函数调用”。

再次从钱伯斯(2008年)那里,他实际上对这一陈述进行了一些限定:

  

R中发生的几乎所有事情都来自函数调用。   因此,基础编程以创建和完善为中心   功能

那么这意味着R中发生的几乎所有数据转换都是函数调用。即使是简单的事情,如括号,也是R中的一个函数。

所以把括号作为一个例子,你实际上可以重新定义它来做这样的事情:

`(` <- function(x) x + 1
(1)
[1] 2

这不是一个好主意,但说明了重点。所以我想这就是我总结的结果:R中存在的所有东西都是一个对象,因为它们是可以被操纵的数据。并且(几乎)发生的所有事情都是函数调用,它是对该对象的评估,它为您提供了另一个对象。

答案 1 :(得分:11)

我喜欢那句话。

在另一篇(截至目前尚未发表)的文章中,作者继续

  

R具有统一的内部结构,用于表示所有对象。评估过程以一种基本上简单的形式关闭该结构   由函数调用组成,对象作为参数,对象作为参数   值。理解R中对象和函数的核心作用   使用该软件对任何具有挑战性的应用程序更有效,即使那些扩展R不是目标的应用程序也是如此。

然后花费数百页扩展它。一旦完成,这将是一个很好的阅读。

答案 2 :(得分:9)

对象对于x来说,对象意味着它有一个类,因此class(x)为每个对象返回一个类。甚至函数都有一个类,环境和人们可能不期望的其他对象:

class(sin)
## [1] "function"

class(.GlobalEnv)
## [1] "environment"

我不会过分关注is.objectis.object(x)与我们在此处使用的含义略有不同 - 如果x内部存储有类名及其值,则返回TRUE。如果存储了类,则class(x)将返回存储的值,如果不存在,则class(x)将根据类型计算它。从概念的角度来看,重要的不是类如何在内部存储(存储或计算) - 重要的是在x两种情况下仍然是一个对象并且仍然有一个类。

函数所有通过函数进行的计算都指的是,即使是你可能不希望成为函数的东西实际上也是函数。例如,当我们写:

{ 1; 2 }
## [1] 2

if (pi > 0) 2 else 3
## [1] 2

1+2
## [1] 3

我们实际上正在调用{if+函数:

`{`(1, 2)
## [1] 2

`if`(pi > 0, 2, 3)
## [1] 2

`+`(1, 2)
## [1] 3