Esto debería hacer ...
(defun take-while (list test)
(and list (funcall test (car list))
(cons (car list) (take-while (cdr list) test))))
(take-while '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) (lambda (x) (< x 10)))
--> (1 2 3 4 5 6 7 8 9)
Sin embargo, esta aplicación "natural" no es recursiva de cola y podría estrellarse para listas grandes
Un enfoque explícito push-nreverse (un patrón común) podría ser
(defun take-while (list test)
(do ((res nil))
((or (null list) (not (funcall test (car list))))
(nreverse res))
(push (car list) res)
(setf list (cdr list))))
Un recursiva (pero recursiva de cola, por lo tanto, probablemente bien con la mayoría de las implementaciones CL) podría ser la OMI lo siguiente:
(defun take-while (list test)
(labels ((rec (res x)
(if (and x (funcall test (car x)))
(rec (cons (car x) res) (cdr x))
(nreverse res))))
(rec nil list)))
Tenga en cuenta que, sin embargo, no se garantiza que una implementación común de lisp manejará las optimizaciones de cola de llamada.
No es una buena idea. Ni siquiera es cola recursiva. Va a explotar la pila en cualquier lista más larga ... –
Gracias por aceptar, pero tenga en cuenta que probablemente danlei respuestas es mejor ... esto ni siquiera es recursivo cola – 6502
@rainer joswig: Estoy de acuerdo que el bucle es mejor – 6502