match.call с предоставленным вызовом функции - PullRequest
0 голосов
/ 01 декабря 2018

Я хотел бы захватить все аргументы и значения и вернуть именованный список.У меня возникла проблема с ситуацией, когда указанное значение является вызовом функции.

Следующее создает объект класса "вызов", что мне неудобно, потому что я хочу вызвать paste для него:

fun1 = function(a = 1) as.list(match.call()[-1])
value1 = fun1(a = letters[1:2])
class(value1[[1]])
[1] "call"
paste(value1[[1]], collapse = " - ")
[1] "[ - letters - 1:2" #not useful to me

В качестве обходного пути я могу вызвать eval, чтобы получить вектор символов, созданный c (функция lapply предназначена для иллюстрации того, что при наличии нескольких аргументов будет вызываться evalна всех них):

fun2 = function(a = 1) lapply(as.list(match.call()[-1]), eval)
value2 = fun2(a = letters[1:2])
class(value2[[1]])
[1] "character"
paste(value2[[1]], collapse = " - ")
[1] "a - b" #that's what I want

Есть ли лучший способ сделать это?Вызов eval для нескольких вещей просто для получения значений кажется мне немного странным.

РЕДАКТИРОВАТЬ: Идея заключается в том, что я хотел бы передать список аргументов функции (которая принимаетименованный список для одного из его аргументов) в исходной функции.Я хотел бы получить значения, предоставленные пользователем, и значения по умолчанию (для аргументов, в которых пользователь ничего не предоставлял).

В другом месте я узнал, что все это можно получить с помощью комбинации match.callи formals.Но затем, скажем, мне нужно передать это аргументу query функции httr::GET и выполнить некоторую обработку перед этим (например, добавить «-» между «a» и «b»).Затем я получаю что-то вроде «[- letters - 1: 2» вместо «a - b».

Я чувствую, что если в ответе используется eval, то я, вероятно, задаю неправильный вопрос.

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Ну, я думаю, вам нужно решить, какая часть вашего кода нуждается в оценке, а какая нет.
Из вашего примера не совсем понятно, насколько вы хотите следовать, но ваш вопрос-пример может быть решен простым списком (), вам нужна только пользовательская функция для предоставления значений по умолчанию:

myfun <- function(a=1) list(a=a)
value <- myfun(a=letters[1:2]))
paste(value[[1]], collapse = " - ")
# Basically: value <- list(a=letters[1:2])), or paste(letters[1:2], collapse= " - ")

Обычно вы используете match.call () без каких-либо аргументов, чтобы выяснить, каким образом была вызвана ваша функция.Иногда полезно знать, был ли вызван fun (a = c ('a', 'b')) или fun1 (a = letters [1: 2]), поэтому match.call сообщает вам об этом, ничего не оценивая.

Так что, если вы действительно хотите что-то сделать со своими аргументами, просто вызовите их напрямую, и позже вы сможете передать их другой функции

mypaste <- function(..., sep=' -CustomSep- ', collapse=' -Mycollapse- ', prefix='Value:') {
  if(length(list(...))>0) {
    paste(prefix, ..., sep=sep, collapse=collapse)
  } else {
    text <- character(0)
  }
}

Эта функция - просто вариант вставки,но вы можете сделать его обширным, как хотите.

И у меня складывается впечатление, что вам нужен общий случай, когда вы сопоставляете свои аргументы с аргументами другой функции, но для ответа на этот вопрос мне нужно знатьбольше о том, что именно вы пытаетесь достичь.

0 голосов
/ 02 декабря 2018

Я чувствую, что вы ищете что-то более общее, поэтому не уверен, что это именно то, что вы ищете, но это проще и дает желаемый результат.Важная часть здесь do.call ()

fun1 = function(a = 1) {
  L1 <- as.list(match.call())
  do.call(paste0, list(L1$a, sep="", collapse=" - "))
}

value1 = fun1(a = letters[1:2])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...