【问题标题】:What's the real meaning about 'Everything that exists is an object' in R?R中“存在的一切都是对象”的真正含义是什么?
【发布时间】:2015-12-19 23:04:56
【问题描述】:

我看到了:

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

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

——约翰·钱伯斯

但我刚刚发现:

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

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

那么,R 中“存在的一切都是对象”的真正含义是什么?

【问题讨论】:

  • 对于许多编程语言,我想你只能调用'x'是一个变量,而不是一个对象,如果'x'只有一个值。
  • 这句话不是关于 is.object() 给出的答案,而是关于 R 中所有内容的内部表示——参见 Dirk Eddelbuettel 的答案。这尤其意味着,例如函数也是对象,公式和表达式也是对象,而且……(……鉴于引用,is.object() 将毫无用处,因为一切都是对象)

标签: r


【解决方案1】:

函数is.object 似乎只查看对象是否具有“类”属性。所以和标语里的意思不一样。

例如:

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>

《钱伯斯》(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中存在的一切都是一个对象,因为它们是可以操作的数据。并且(几乎)所有发生的事情都是一个函数调用,这是对这个对象的评估,它为您提供另一个对象。

【讨论】:

  • 嗨@Carlos,我想现在我知道R中“对象”的定义。正如你所说,对象只是一种可以操作的数据结构。这与其他语言完全不同,例如 Python、Ruby、Java。我想那是因为 R 有不同的类系统。
  • and is.object(x) 为 FALSE,仅表示该对象还没有属性。就是这样。实际上,我认为 R 没有真正的类系统,R 也不需要它。由于它是一种函数式语言,所有的类系统都只是语法糖,而且有点难看。
【解决方案2】:

我喜欢这句话。

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

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

但随后会花费数百页对其进行扩展。读完后会很精彩。

【讨论】:

    【解决方案3】:

    对象 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2013-02-02
      • 2017-05-06
      • 2012-03-30
      • 2011-10-10
      • 2012-08-03
      • 2012-01-30
      相关资源
      最近更新 更多