This vignette goes into slightly more detail than the other vignettes about memory representations and C code.
You might be surprised to discover that an ALTREP
is
actually stored using the same memory layout as an R pairlist, which is
the same data structure used to store formal arguments:
R pairlists hold 3 pointers, (called the CAR
,
CDR
and TAG
)1. ALTREPs re-use this
structure to point to the three parts of an ALTREP2:
-
CAR
-> data1: internal data, as aSEXPREC
(normal R object) -
CDR
-> data2: more internal data (also aSEXPREC
) -
TAG
-> class: The ALTREP class, as a raw vector with attributes
In addition, ALTREPs are distinguished from other R structures via
the ALTREP
flag, which is set to 13.
By now you are probably familiar with alt_data1()
and
alt_data2()
for prying into those first two fields. But for
the TAG
, altrepr
actually has another trick up
its sleeve: alt_class()
.
As mentioned, the ALTREP class, not to be confused with the ALTREP class name, is a raw vector. We can look at it, but it’s not particularly interesting:
library(altrepr)
alt_class(1:3)
#> [1] 50 90 47 87 77 7f 00 00 c0 4c 47 87 77 7f 00 00 e0 49 47 87 77 7f 00 00 b0
#> [26] 90 47 87 77 7f 00 00 b0 67 47 87 77 7f 00 00 20 4f 47 87 77 7f 00 00 e0 66
#> [51] 47 87 77 7f 00 00 00 4a 47 87 77 7f 00 00 10 51 47 87 77 7f 00 00 30 4d 47
#> [76] 87 77 7f 00 00 d0 8d 47 87 77 7f 00 00 10 74 47 87 77 7f 00 00 90 60 47 87
#> [101] 77 7f 00 00 30 4a 47 87 77 7f 00 00 c0 49 47 87 77 7f 00 00 a0 4a 47 87 77
#> [126] 7f 00 00 d0 94 47 87 77 7f 00 00 e0 94 47 87 77 7f 00 00
#> Error in print.default(x): 'getCharCE' must be called on a CHARSXP
One potential utility of this is checking if two objects belong to the same class (although R prefers to compare pointers rather than vector values for this kind of thing)4.
Possibly more interesting is the attributes of the class, which is where we get all the juicy details:
1:5 |>
alt_class() |>
attributes()
#> [[1]]
#> compact_intseq
#>
#> [[2]]
#> base
#>
#> [[3]]
#> [1] 13
Notice that this is the source for many of the fields returned by
alt_details
:
alt_details(1:5)
#> $class_name
#> [1] "compact_intseq"
#>
#> $pkg_name
#> [1] "base"
#>
#> $base_type
#> [1] "integer"
#>
#> $data1
#> [1] 5 1 1
#>
#> $data2
#> NULL