[Rd] some questions about R internal SEXP types

Gabriel Becker
Mon, 07 Sep 2020 21:38:12 -0000

Dan,

Sounds like a cool project! Response to one of your questions inline

On Mon, Sep 7, 2020 at 4:24 AM Dan Kortschak via R-devel <
r-devel at r-project.org> wrote:

>
> The last question is more a question of interest in design strategy,
> and the answer may have been lost to time. In order to reduce the need
> to go through Go's interface assertions in a number of cases I have
> decided to reinterpret R_NilValue to an untyped Go nil (this is
> important for example in list traversal where the CDR can (hopefully)
> be only one of two types LISTSXP or NILSXP; in Go this would require a
> generalised SEXP return, but by doing this reinterpretation I can
> return a *List pointer which may be nil, greatly simplifying the code
> and improving the performance). My question her is why a singleton null
> value was chosen to be represented as a fully allocated SEXP value
> rather than just a C NULL. Also, whether C NULL is used to any great
> extent within the internal code.


I cannot speak to initial intent, perhaps others can. I can say that there
is at least one place where the difference between R_NilValue and NULL is
very important as of right now. The current design of the ALTREP framework
contract expects ALTREP methods that return a SEXP to return C NULL when
they fail (or decline) to do the requested computation and the
non-altclass-specific machinery should be run as a fallback. The places
where ALTREP methods are plugged into the existing, general internals then
check for C-NULL after attempting to fast-path the computation via ALTREP.
Any non-C-NULL SEXP, including R_Nilvalue will be taken as an indication
that the altrep-method succeeded and that SEXP is the resulting value,
causing the fall-back machinery to be skipped.

IIUC the system you described, this means that it would be impossible to
implement (a fully general) ALTREP class in GO using your framework (at
least for the method types that return SEXP and for which R_NilValue is a
valid return value) because your code is unable to distinguish safely
between the two. In practice in most currently existing methods, you
wouldn't ever need to return R_NilValue, I wouldn't think.

The problem that jumps out at me is Extract_subset. Now I'd need to do some
digging to be certain but there, for some types in some situations, it DOES
*seem* like you might need to return the R-NULL and find yourself unable to
do so.

Its also possible more methods will be added to the table in the future
that would be problematic in light of that restrictrion.

In particular, if ALTREP list/environment implementations were to ever be
supported I would expect you to be dead in the water entirely in terms of
building those as you'd find yourself entirely unable to implement the
Basic Single-element getter machinery, I think.

Beyond that, a quick grep of the sources tells me there are definitely a
few times SEXP objects are tested with == NULL though not
overwhelmingly many. Most such tests are for non-SEXP pointers.

Best,
~G



> Note that the Go API provides a
> mechanism to easily reconvert the nil's used back to a R_NilValue when
> returning from a Go function[3].
>
> thanks
> Dan Kortschak
>
> [1]https://github.com/rgonomic/rgo
> [2]https://github.com/rgonomic/rgo/issues/1
> [3]https://pkg.go.dev/github.com/rgonomic/rgo/sexp?tab=doc#Value.Export
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

	[[alternative HTML version deleted]]