Skip to content

API for converting LANGSXP to LISTSXP?

4 messages · Kevin Ushey, Ivan Krylov, iuke-tier@ey m@iii@g oii uiow@@edu

#
Hi,

A common idiom in the R sources is to convert objects between LANGSXP
and LISTSXP by using SET_TYPEOF. However, this is soon going to be
disallowed in packages. From what I can see, there isn't currently a
direct way to convert between these two object types using the
available API. At the R level, one can convert calls to pairlists
with:
rnorm(42)

However, the reverse is not possible:
Error in as.pairlist(call("rnorm", 42)) :
  'language' object cannot be coerced to type 'pairlist'

One can do such a conversion via conversion to e.g. an intermediate R
list (VECSXP), but that seems wasteful. Would it make sense to permit
this coercion? Or, is there some other relevant API I'm missing?

For completeness, Rf_coerceVector() also emits the same error above
since it uses the same code path.

Thanks,
Kevin
1 day later
#
On Fri, 5 Jul 2024 15:27:50 +0800
Kevin Ushey <kevinushey at gmail.com> wrote:

            
Would you mind providing an example where a package needs to take an
existing LISTSXP and convert it to a LANGSXP (or vice versa)? I think
that Luke Tierney intended to replace the uses of
SET_TYPEOF(allocList(...), LANGSXP) with allocLang(...).

At least it's easy to manually convert between the two by replacing the
head of the list using LCONS(CAR(list), CDR(list)) or CONS(CAR(lang),
CDR(lang)): in a call, the rest of the arguments are ordinary LISTSXPs.
#
We have long been discouraging the use of pairlists. So no, we will
not do anything to facilitate this conversion; if anything the
opposite. SET_TYPEOF is used more than it should be in the sources.
It is something I would like us to fix sometime, but isn't high
priority.

Best,

luke
On Fri, 5 Jul 2024, Kevin Ushey wrote:

            

  
    
#
In this case, Rcpp was internally converting (already-existing)
LISTSXPs to LANGSXPs using SET_TYPEOF in some places; the goal was to
allow Rcpp to continue doing this without using SET_TYPEOF just to
preserve existing behavior in an API-compliant way. I ended up doing
exactly what you suggested; thanks.
On Sat, Jul 6, 2024 at 8:09?PM Ivan Krylov <ikrylov at disroot.org> wrote: