Mantengo un paquete que se basa en llamadas repetidas a deparse(control = c("keepNA", "keepInteger")). controles siempre igual, y la expresión varía. deparse()parece pasar mucho tiempo interpretando repetidamente el mismo conjunto de opciones con .deparseOpts().
microbenchmark::microbenchmark(
a = deparse(identity, control = c("keepNA", "keepInteger")),
b = .deparseOpts(c("keepNA", "keepInteger"))
)
# Unit: microseconds
# expr min lq mean median uq max neval
# a 7.2 7.4 8.020 7.5 7.6 55.1 100
# b 3.0 3.2 3.387 3.4 3.5 6.0 100
En algunos sistemas, las .deparseOpts()llamadas redundantes en realidad ocupan la mayor parte del tiempo de ejecución de deparse()( gráfico de llama aquí ).
Realmente me gustaría llamar .deparseOpts()una vez y luego proporcionar el código numérico deparse(), pero eso parece imposible sin llamar .Internal()o invocar el código C directamente, ninguno de los cuales es óptimo desde la perspectiva del desarrollo del paquete.
deparse
# function (expr, width.cutoff = 60L, backtick = mode(expr) %in%
# c("call", "expression", "(", "function"),
# control = c("keepNA", "keepInteger", "niceNames",
# "showAttributes"), nlines = -1L)
# .Internal(deparse(expr, width.cutoff, backtick, .deparseOpts(control),
# nlines))
# <bytecode: 0x0000000006ac27b8>
# <environment: namespace:base>
¿Hay una solución conveniente?

backtickargumento, el análisis es 6 veces más rápido. Me voy con eso. Muchas gracias por la solución!R CMD checkdetecta la.Internal()llamada en funciones producidas por (1). Bastante fácil de solucionar, solo necesitomake_deparse()(expr, control = 64, backtick = TRUE). Es una tontería reconstruir el analizador cada vez que lo uso, pero aún es mucho más rápido que el ingenuodeparse()que estaba usando antes.make_deparseyRunen (1) y ejecutéR CMD buildyR CMD check --as-crandebajo"R version 3.6.1 Patched (2019-11-18 r77437)"y no se quejó y no necesité ninguna solución. ¿Estás seguro de que no estás haciendo algo diferente o que además está causando esto?direct_deparse <- make_direct_deparse(). El código que se muestra en la respuesta tuvo cuidado de no hacer eso y solo lo definió dentro de una función, es decir, dentroRun.