Получить все параметры в виде списка


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
Это не удастся, если значения по умолчанию не переопределены при вызове функции. Он не будет перечислять аргумент с установленным по умолчанию, но не переопределенным.

Известно ли вам о пакете, который экспортирует такую ​​функцию (только ...с параметром as)?
krlmlr 08

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

Это создает именованный список значений аргументов.


Известно ли вам о пакете, который экспортирует такую ​​функцию (только ...с параметром as)?
krlmlr 08

2
или просто напечатайте (as.list (environment ())), если у вас нет ... в качестве аргумента
RockScience

3
Это отлично работает, у него есть преимущество перед принятым ответом в том, что он фиксирует значения, переданные функции, а не выражения, которые можно использовать для вычисления значений. Если вы пытаетесь сохранить аргументы, чтобы вы могли вызвать функцию позже, вероятно, вам нужны значения.
Кен Уильямс

1
Возможно, стоит отметить, что обычно важно «захватить» аргументы, запустив их argg <- c(as.list(environment()), list(...))в самом начале вашей функции. В противном случае в environment()конечном итоге будут включены другие переменные, созданные внутриtempf()
mkirzon

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, например, предсказать. Так что глупо искать в другом месте, чтобы запомнить тот единственный параметр / флаг, который вы пытались запомнить.
D, возможно,

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
В чем преимущество использования этого метода по сравнению с уже предложенными решениями? В частности, это кажется очень похожим на ответ user399470
Мэтт Саммерсгилл

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

Создано 25.02.2020 с помощью пакета REPEX (v0.3.0)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.