Obtener todos los parámetros como lista

80

¿R proporciona un objeto / función / método / palabra clave para obtener todos los argumentos de la función?

Usando un ejemplo: function(a, b="default", ...)proporcionaría ay basí como ...dentro del entorno de la función. ¿Hay una declaración similar a la list(...)que también incluiría ay ben el resultado?

O dicho de otra manera: una abreviatura de list(a=a, b=b, ...), dadofunction(a, b, ...)

Lukas Grebe
fuente
1
El problema de esta pregunta es que no está claro lo que está preguntando. ¿Está preguntando cómo obtener 1) los valores con los que se llamó a la función; 2) las expresiones con las que se llamó a la función; 3) ¿los valores predeterminados en la definición de la función? Su pregunta no tiene nada claro, por lo que tiene 3 tipos diferentes de respuestas para todas estas 3 opciones.
TMS

Respuestas:

67

Creo que quieres match.call:

tmpfun <- function(a,b,...) {
print(as.list(match.call()))
print(as.list(match.call(expand.dots=FALSE)))
}
> tmpfun(a=1, b=2, c=3, d=4)
[[1]]
tmpfun

$a
[1] 1

$b
[1] 2

$c
[1] 3

$d
[1] 4

[[1]]
tmpfun

$a
[1] 1

$b
[1] 2

$...
$...$c
[1] 3

$...$d
[1] 4
Greg Snow
fuente
23
Esto falla si los valores predeterminados no se anulan en la llamada a la función. No enumerará el argumento con el conjunto predeterminado pero no anulado.
¿Conoce un paquete que exporta dicha función (con solo ...como parámetro)?
krlmlr
5
Esto no funciona cuando tmpfun recibió argumentos de otra función contenedora. (la lista solo tiene los argumentos no evaluados)
RockScience
1
Por estas razones, la respuesta aceptada debe ser la de @ user399470 que usa c(as.list(environment()), list(...))que captura tanto los argumentos predeterminados como los argumentos proporcionados.
Lorenz Walthert
77

Una solución es utilizar:

tempf <- function(a, b = 2, ...) {
    argg <- c(as.list(environment()), list(...))
    print(argg)
}
tempf(1, c = 3)
$a
[1] 1

$b
[1] 2

$c
[1] 3

Esto crea una lista con nombre de los valores de los argumentos.


fuente
¿Conoce un paquete que exporta dicha función (con solo ...como parámetro)?
krlmlr
2
o simplemente imprima (as.list (environment ())) si no tiene ... como argumento
RockScience
3
Esto funciona muy bien, tiene la ventaja sobre la respuesta aceptada de que captura los valores pasados ​​a la función, en lugar de las expresiones que se pueden usar para calcular los valores. Si está intentando guardar los argumentos para poder llamar a la función más tarde, probablemente desee los valores.
Ken Williams
1
Vale la pena señalar que normalmente es importante "capturar" los argumentos ejecutándolos argg <- c(as.list(environment()), list(...))al principio de la función. De lo contrario, environment()terminará incluyendo otras variables que se crean dentrotempf()
mkirzon
12

prueba la argsfunción

¿Cuáles son los argumentos a favor de la meanfunción?

> args(mean)
function (x, ...) 
NULL

¿Y la lmfunción?

    > args(lm)
function (formula, data, subset, weights, na.action, method = "qr", 
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, 
    contrasts = NULL, offset, ...) 
NULL

Si desea obtener una lista de argumentos, intente

as.list(args(lm))
Jilber Urbina
fuente
Es una pena que más funciones no cooperen con la llamada a args, como predecir. Es una tontería tener que ir a otro lado para recordar ese parámetro / bandera que estabas tratando de recordar.
D Quizás
9

Me encontré con esta pregunta mientras buscaba algo relacionado. Si bien me doy cuenta de que esto tiene varios años, las respuestas parecen insatisfactorias y no parece haber ninguna solución estándar para la pregunta.

Es posible hacer una solución alternativa (poco elegante), utilizando una combinación de las funciones formalsy environment. El siguiente ejemplo extrae argumentos del entorno utilizando nombres extraídos de formales, luego agrega la lista de puntos suspensivos. Si desea tener los valores como se establecieron en el momento de la llamada a la función, establezca el argumento orig_values ​​en TRUE. La función solo incluye variables establecidas implícita o explícitamente en la llamada a la función.

allargs <- function(orig_values = FALSE) {
  # get formals for parent function
  parent_formals <- formals(sys.function(sys.parent(n = 1)))

  # Get names of implied arguments
  fnames <- names(parent_formals)

  # Remove '...' from list of parameter names if it exists
  fnames <- fnames[-which(fnames == '...')]

  # Get currently set values for named variables in the parent frame
  args <- evalq(as.list(environment()), envir = parent.frame())

  # Get the list of variables defined in '...'
  args <- c(args[fnames], evalq(list(...), envir = parent.frame()))


  if(orig_values) {
    # get default values
    defargs <- as.list(parent_formals)
    defargs <- defargs[unlist(lapply(defargs, FUN = function(x) class(x) != "name"))]
    args[names(defargs)] <- defargs
    setargs <- evalq(as.list(match.call())[-1], envir = parent.frame())
    args[names(setargs)] <- setargs
  }
  return(args)
}


tempf <- function(a, b = 2, ...) {
  d <- 5
  b <- 3

  cat("Currently set values defined in call or formals\n")
  print(allargs())
  cat("Values as defined at the time of the call\n")
  print(allargs(T))
}

tempf(1, c = 3)

Currently set values defined in call or formals
$a
[1] 1

$b
[1] 3

$c
[1] 3

Values as defined at the time of the call
$a
[1] 1

$b
[1] 2

$c
[1] 3
Accidente inteligente
fuente
6

Creo que estas buscando formals:

formals(sd)
$x


$na.rm
[1] FALSE

Y usar dputesto le da el formulario que especifica en la pregunta:

dput(formals(sd))
list(x = , na.rm = FALSE)

Tenga en cuenta que formalsno funciona para funciones primitivas , solo cierres.

James
fuente
2
esto solo enumera los argumentos predeterminados .
RockScience
1
test <- function(
  x = 1,
  y = 2,
  ...
) {
  if(length(list(...)) == 0) {
    print(as.list(environment()))
  } else {
    print(c(as.list(environment()), list(...)))
  }
}

test()
test(z = 3)
moza
fuente
3
¿Cuál sería el beneficio de utilizar este método sobre las soluciones ya propuestas? En particular, esto parece ser extremadamente similar a la respuesta del usuario399470
Matt Summersgill
1

rlang::fn_fmls da una solución breve y limpia:

library(ggplot2)
library(rlang)

# action
argument_list <- rlang::fn_fmls(fn = geom_point)

# evaluate output
class(argument_list)
#> [1] "pairlist"

is.list(argument_list)
#> [1] TRUE

argument_list
#> $mapping
#> NULL
#> 
#> $data
#> NULL
#> 
#> $stat
#> [1] "identity"
#> 
#> $position
#> [1] "identity"
#> 
#> $...
#> 
#> 
#> $na.rm
#> [1] FALSE
#> 
#> $show.legend
#> [1] NA
#> 
#> $inherit.aes
#> [1] TRUE

Creado el 2020-02-25 por el paquete reprex (v0.3.0)

avallecam
fuente