-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbase-types.qmd
154 lines (102 loc) · 6.58 KB
/
base-types.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Tipos básicos {#sec-base-types}
## Introducción
\index{base objects} \index{OO objects}
```{r setup, include = FALSE}
source("common.R")
```
Para hablar de objetos y programación orientada a objetos en R, primero debemos aclarar una confusión fundamental sobre dos usos de la palabra "objeto". Hasta ahora en este libro, hemos usado la palabra en el sentido general captado por la concisa cita de John Chambers: "Todo lo que existe en R es un objeto". Sin embargo, aunque todo *es* un objeto, no todo está orientado a objetos. Esta confusión surge porque los objetos base provienen de S y se desarrollaron antes de que nadie pensara que S podría necesitar un sistema OOP. Las herramientas y la nomenclatura evolucionaron orgánicamente durante muchos años sin un solo principio rector.
La mayoría de las veces, la distinción entre objetos y objetos orientados a objetos no es importante. Pero aquí tenemos que entrar en detalles esenciales, así que usaremos los términos **objetos base** y **objetos OO** para distinguirlos.
```{r, out.width = NULL, echo = FALSE}
knitr::include_graphics("diagrams/oo-venn.png")
```
### Estructura {.unnumbered}
- La @sec-base-vs-oo le muestra cómo identificar objetos base y OO.
- La @sec-base-types-2 proporciona un conjunto completo de los tipos base utilizados para construir todos los objetos.
## Base versus objetos OO {#sec-base-vs-oo}
```{=tex}
\index{is.object()}
\index{otype()}
```
\index{attributes!class} \index{class()}
Para saber la diferencia entre un objeto base y OO, usa `is.object()` o `sloop::otype()`:
```{r}
# Un objeto básico:
is.object(1:10)
sloop::otype(1:10)
# Un objeto OO
is.object(mtcars)
sloop::otype(mtcars)
```
Técnicamente, la diferencia entre los objetos base y OO es que los objetos OO tienen un atributo de "clase":
```{r}
attr(1:10, "class")
attr(mtcars, "class")
```
Puede que ya estés familiarizado con la función `class()`. Es seguro aplicar esta función a objetos S3 y S4, pero devuelve resultados engañosos cuando se aplica a objetos base. Es más seguro usar `sloop::s3_class()`, que devuelve la clase implícita que los sistemas S3 y S4 usarán para seleccionar métodos. Aprenderá más sobre `s3_class()` en la @sec-implicit-class.
```{r}
x <- matrix(1:4, nrow = 2)
class(x)
sloop::s3_class(x)
```
## Tipos básicos {#sec-base-types-2}
\index{typeof()}
\index{base type|see {\texttt{typeof()}}}
Mientras que solo los objetos OO tienen un atributo de clase, cada objeto tiene un **tipo base**:
```{r}
typeof(1:10)
typeof(mtcars)
```
Los tipos base no forman un sistema OOP porque las funciones que se comportan de manera diferente para diferentes tipos base se escriben principalmente en código C que usa instrucciones de cambio. Esto significa que solo R-core puede crear nuevos tipos, y crear un nuevo tipo es mucho trabajo porque cada declaración de cambio debe modificarse para manejar un nuevo caso. Como consecuencia, rara vez se agregan nuevos tipos base. El cambio más reciente, en 2011, agregó dos tipos exóticos que nunca se ven en R, pero que son necesarios para diagnosticar problemas de memoria. Antes de eso, el último tipo agregado fue un tipo base especial para objetos S4 agregado en 2005.
```{=html}
<!--
https://github.com/wch/r-source/blob/f5bb85782509ddadbcec94ab7648886c2d008bda/src/main/util.c#L185-L211-->
```
En total, hay 25 tipos de base diferentes. Se enumeran a continuación, agrupados libremente según el lugar en el que se analicen en este libro. Estos tipos son los más importantes en el código C, por lo que a menudo los verá llamados por sus nombres de tipo C. Los he incluido entre paréntesis.
- Vectores, @sec-vectors-chap, incluye tipos `NULL` (`NILSXP`), `logical` (`LGLSXP`), `integer` (`INTSXP`), `double` (`REALSXP`), `complex` (`CPLXSXP`), `character` (`STRSXP`), `list` (`VECSXP`), y `raw` (`RAWSXP`).
```{r}
typeof(NULL)
typeof(1L)
typeof(1i)
```
- Las funciones, @sec-functions, incluyen los tipos `cierre` (funciones regulares de R, `CLOSXP`), `especiales` (funciones internas, `SPECIALSXP`) e `incorporadas` (funciones primitivas, `BUILTINSXP`).
```{r}
typeof(mean)
typeof(`[`)
typeof(sum)
```
Las funciones internas y primitivas se describen en la @sec-primitive-functions.
- Entornos, @sec-environments, tienen tipo `entorno` (`ENVSXP`).
```{r}
typeof(globalenv())
```
- El tipo `S4` (`S4SXP`), @sec-s4, se usa para las clases de S4 que no heredan de un tipo base existente.
```{r}
mle_obj <- stats4::mle(function(x = 1) (x - 2) ^ 2)
typeof(mle_obj)
```
- Los componentes del lenguaje, @sec-expressions), incluyen `símbolo` (también conocido como nombre, `SYMSXP`), `idioma` (generalmente llamadas llamadas, `LANGSXP`) y `pairlist` (usado para argumentos de función, `LISTSXP` ) tipos.
```{r}
typeof(quote(a))
typeof(quote(a + 1))
typeof(formals(mean))
```
`expression` (`EXPRSXP`) es un tipo de propósito especial que solo es devuelto por `parse()` y `expression()`. Las expresiones generalmente no son necesarias en el código de usuario.
- Los tipos restantes son esotéricos y rara vez se ven en R. Son importantes principalmente para el código C: `externalptr` (`EXTPTRSXP`), `weakref` (`WEAKREFSXP`), `bytecode` (`BCODESXP`), `promise` (`PROMSXP`), `...` (`DOTSXP`), y `any` (`ANYSXP`).
\index{mode()}
Es posible que hayas oído hablar de `mode()` y `storage.mode()`. No utilice estas funciones: solo existen para proporcionar nombres de tipo que sean compatibles con S.
### Tipo numérico {#sec-numeric-type}
\index{numeric vectors} \index{vectors!numeric|see {numeric vectors}}
Tenga cuidado al hablar del tipo numérico, porque R usa "numérico" para referirse a tres cosas ligeramente diferentes:
1. En algunos lugares, numérico se usa como un alias para el tipo doble. Por ejemplo, `as.numeric()` es idéntico a `as.double()`, y `numeric()` es idéntico a `double()`.
(R también usa ocasionalmente real en lugar de doble; `NA_real_` es el único lugar donde es probable que encuentres esto en la práctica.)
2. En los sistemas S3 y S4, numérico se usa como una forma abreviada de tipo entero o doble, y se usa cuando se seleccionan métodos:
```{r}
sloop::s3_class(1)
sloop::s3_class(1L)
```
3. `is.numeric()` pruebas para objetos que se *comportan* como números. Por ejemplo, los factores tienen el tipo "entero" pero no se comportan como números (es decir, no tiene sentido tomar la media del factor).
```{r}
typeof(factor("x"))
is.numeric(factor("x"))
```
En este libro, siempre uso numérico para indicar un objeto de tipo entero o doble.