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 CHARSXPOne 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] 13Notice 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