O que você queria fazer era dobrar ou desdobrar uma sequência de objetos do mesmo tipo. É tentador usar apply
para esse fim, porque em muitos casos realmente funcionará. Mas não é exatamente a ferramenta certa para isso, e aqui está o porquê:
apply
é um mecanismo de metaprogramação, não apenas isso, também é muito geral para a tarefa, pois pode lidar com seqüências de objetos de tipos diferentes, não necessariamente chamando funções de dois argumentos. Como consequência, algumas vezes você obtém um comportamento incorreto, por exemplo:
(apply 'concat "baz" '("foo" "bar"))
> "bazfoobar"
Mas, intuitivamente, você esperaria uma incompatibilidade de tipo aqui.
Não há como garantir apply
que seja possível processar o máximo de argumentos que você puder fornecer; normalmente é um limite imposto pela implementação do idioma.
A função chamada por apply
poderá obter uma referência da lista de argumentos passada a ela dessa maneira. Isso também não é óbvio e pode levar a erros mais tarde:
(let ((test (list 1 2 3)))
(cons
(apply (lambda (&rest x)
(prog1 (cl-reduce '+ x) (setcar x 0)))
test)
test))
;; This behaviour is undefined. Could end up both ways
> (6 1 2 3)
> (6 0 2 3)
Se a lista de argumentos for copiada, você pagará o preço de consumir mais memória do que o necessário, mas se não for copiada (passada como está), corre o risco de estragar a lista, se a função chamada modificá-la.
Então, a melhor maneira de fazer isso é usar cl-reduce
. O benefício é que ele foi projetado especificamente para executar esse tipo de tarefa.
(cl-reduce 'concat '("foo" "bar" "baz"))
> "foobarbaz"