Lo que quería hacer parece doblar o desdoblar una secuencia de objetos del mismo tipo. Es tentador usarlo apply
para este propósito, porque en muchos casos sí funcionará. Pero no es exactamente la herramienta adecuada para esto, y esta es la razón:
apply
es un mecanismo de metaprogramación, no solo eso, también es demasiado general para la tarea porque puede manejar secuencias de objetos de diferentes tipos, no necesariamente llamando a funciones de dos argumentos. Como consecuencia, algunas veces obtendrá un comportamiento incorrecto, por ejemplo:
(apply 'concat "baz" '("foo" "bar"))
> "bazfoobar"
Pero intuitivamente, esperaría un desajuste de tipo aquí.
No hay forma de asegurarse de apply
que pueda procesar tantos argumentos como pueda, normalmente es un límite impuesto por la implementación del lenguaje.
La función llamada por apply
podrá obtener una referencia de la lista de argumentos que se le pasa de esta manera. Esto tampoco es obvio y puede provocar errores más adelante:
(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)
Si se copia la lista de argumentos, entonces paga el precio de conservar más memoria de la necesaria, pero si no se copia (se pasa como está), corre el riesgo de estropear la lista, si la función que se llama la modifica.
Entonces, la mejor manera de hacerlo es usarlo cl-reduce
. El beneficio es que fue diseñado específicamente para hacer este tipo de tareas.
(cl-reduce 'concat '("foo" "bar" "baz"))
> "foobarbaz"