我看到了:
“要理解R中的计算,两个口号是有帮助的:
•存在的一切都是一个对象 •发生的一切都是函数调用。“
- John Chambers
但我刚发现:
a <- 2
is.object(a)
# FALSE
实际上,如果变量是纯基类型,则结果是.object()将为FALSE。所以它不应该是一个对象。
那么“R中存在的所有东西是一个物体”的真正含义是什么?
答案 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.object
。 is.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