Отримати всі параметри як список


80

Чи надає R об'єкт / функцію / метод / ключове слово для отримання всіх аргументів функції?

На прикладі: function(a, b="default", ...)забезпечить aі b, а також... у функції середовища. Чи існує твердження, подібне до list(...)того, яке також містило б aі bрезультат?

Або по-іншому: скорочення для list(a=a, b=b, ...), даноfunction(a, b, ...)


1
Проблема цього питання полягає в тому, що незрозуміло, про що ви питаєте. Ви запитуєте, як отримати 1) значення, з якими була викликана функція; 2) вирази, з якими була викликана функція; 3) значення за замовчуванням у визначенні функції? З вашого запитання це зовсім не зрозуміло, тому ви отримали 3 різні типи відповідей на всі ці 3 варіанти.
TMS

Відповіді:


67

Я думаю, що ви хочете 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

23
Це не вдається, якщо за замовчуванням у виклику функції не перевизначено. Він не буде перераховувати аргумент із набором за замовчуванням, але не замінений.

Чи знаєте ви про пакет, який експортує таку функцію (лише з ... як параметр)?
krlmlr

5
Це не працює, коли tmpfun отримував аргументи від іншої функції обгортки. (у списку є лише неоцінені аргументи)
неоцінені

1
З цих причин прийнятою відповіддю має бути відповідь від @ user399470, яка використовує, c(as.list(environment()), list(...))що фіксує як аргументи за замовчуванням, так і надані аргументи.
Lorenz Walthert

77

Одним із рішень є використання:

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

Це створює іменований список значень аргументів.


Чи знаєте ви про пакет, який експортує таку функцію (лише ...як параметр)?
krlmlr

2
або просто роздрукуйте (as.list (environment ())), якщо у вас немає ... як аргумент
RockScience

3
Це чудово працює, він має перевагу перед прийнятою відповіддю, що фіксує значення, передані функції, а не вирази, які можна використовувати для обчислення значень. Якщо ви намагаєтеся зберегти аргументи, щоб пізніше викликати функцію, ви, мабуть, хочете значення.
Кен Вільямс

1
Можливо, варто зазначити, що зазвичай важливо "захопити" аргументи, запустивши argg <- c(as.list(environment()), list(...))на самому початку своєї функції. В іншому випадку environment()в кінцевому підсумку буде tempf()
включено

12

спробуй args функцію

Які аргументи для meanфункції?

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

Що стосовно lm функції?

    > 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

Якщо ви хочете отримати список аргументів, спробуйте

as.list(args(lm))

Погано, більше функцій не співпрацюють із аргументом args, таким як передбачення. Отже, хамбаг, щоб вам довелося піти в інше місце, щоб запам'ятати той параметр / прапор, який ви намагалися запам'ятати.
DC, можливо

9

Натрапив на це питання під час пошуку чогось пов’язаного. Хоча я усвідомлюю, що цьому вже кілька років, відповіді здаються незадовільними, і, схоже, немає будь-якого готового рішення питання.

Можна зробити (неелегантний) обхідний шлях, використовуючи комбінацію функцій formalsі environment. Наведений нижче приклад витягує аргументи із середовища за допомогою імен, витягнутих із формалів, а потім додає список багатоточия. Якщо ви хочете, щоб значення були такими, як вони були встановлені під час виклику функції, встановіть для аргументу orig_values ​​значення TRUE. Функція включає лише змінні, явно або явно встановлені під час виклику функції.

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

6

Я вважаю, що ви шукаєте formals:

formals(sd)
$x


$na.rm
[1] FALSE

І використання dputцього дає вам форму, яку ви вказали у питанні:

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

Зверніть увагу, що formalsце не працює для примітивних функцій, лише закриття.


2
тут перераховані лише аргументи за замовчуванням .
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)

3
Яка була б користь від використання цього методу перед уже запропонованими рішеннями? Зокрема, це, схоже, надзвичайно схоже на відповідь користувача399470
Метт Саммерсгілл,

1

rlang::fn_fmls дає коротке та чисте рішення:

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

Створено 2020-02-25 пакетом reprex (v0.3.0)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.