A linguagem R possui um recurso bacana para definir funções que podem receber um número variável de argumentos. Por exemplo, a função data.frame
aceita qualquer número de argumentos e cada argumento se torna os dados de uma coluna na tabela de dados resultante. Exemplo de uso:
> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
letters numbers notes
1 a 1 do
2 b 2 re
3 c 3 mi
A assinatura da função inclui reticências, assim:
function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
Eu gostaria de escrever uma função que faça algo semelhante, pegando vários valores e consolidando-os em um único valor de retorno (além de fazer outro processamento). Para fazer isso, preciso descobrir como "descompactar" os ...
argumentos da função dentro da função. Eu não sei como fazer isso. A linha relevante na definição de função de data.frame
é object <- as.list(substitute(list(...)))[-1L]
, da qual não consigo entender.
Então, como posso converter as reticências da assinatura da função em, por exemplo, uma lista?
Para ser mais específico, como posso escrever get_list_from_ellipsis
no código abaixo?
my_ellipsis_function(...) {
input_list <- get_list_from_ellipsis(...)
output_list <- lapply(X=input_list, FUN=do_something_interesting)
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
Editar
Parece que existem duas maneiras possíveis de fazer isso. Eles são as.list(substitute(list(...)))[-1L]
e list(...)
. No entanto, esses dois não fazem exatamente a mesma coisa. (Para as diferenças, veja exemplos nas respostas.) Alguém pode me dizer qual é a diferença prática entre eles e qual devo usar?
list
ec
funcionam dessa maneira, mas ambas são primitivas, portanto não posso inspecionar facilmente o código-fonte para entender como elas funcionam.rbind.data.frame
use desta maneira.list(...)
for suficiente, por que os Rins internos, comodata.frame
o formulário mais longo , usamas.list(substitute(list(...)))[-1L]
?data.frame
, eu não sei a resposta para isso (o que disse, eu tenho certeza que não é uma boa razão para isso). Eu usolist()
para esse fim em meus próprios pacotes e ainda tenho que encontrar um problema com ele.Apenas para acrescentar às respostas de Shane e Dirk: é interessante comparar
com
Tal como está, qualquer uma das versões parece adequada para seus propósitos
my_ellipsis_function
, embora a primeira seja claramente mais simples.fonte
Você já deu metade da resposta. Considerar
Então, isso levou dois argumentos
a
eb
da chamada e converteu-o em uma lista. Não foi isso que você pediu?fonte
[[1]]
. Além disso, gostaria de saber como funciona o encantamento mágicoas.list(substitute(list(...)))
.list(...)
cria umlist
objeto com base nos argumentos. Em seguida,substitute()
cria a árvore de análise para a expressão não avaliada; consulte a ajuda para esta função. Bem como um bom texto avançado sobre R (ou S). Isso não é coisa trivial.[[-1L]]
parte (da minha pergunta)? Não deveria ser[[1]]
?print(c(1:3)[-1])
, imprimirá apenas 2 e 3. AL
é uma maneira novos e desnecessários para garantir que ele acaba como um número inteiro, isso é feito muito em fontes de P.[[1]]
e os$a
índices me fez pensar que listas aninhadas estavam envolvidos. Mas agora vejo que o que você realmente recebe é a lista que eu quero, mas com um elemento extra na frente. Então, isso[-1L]
faz sentido. De onde vem esse primeiro elemento extra? E existe alguma razão para eu usar isso em vez de simplesmentelist(...)
?Isso funciona conforme o esperado. A seguir, uma sessão interativa:
Mesmo, exceto com um argumento padrão:
Como você pode ver, você pode usar isso para passar argumentos 'extras' para uma função dentro da sua função se os padrões não forem o que você deseja em um caso específico.
fonte