Pregunta

Dada una lista de valores, que quieren reducir la lista a T si todos los elementos que no son nulas, NIL en caso contrario. Esto me da un error:

(apply #'and (get-some-list))

A medida que hace esto:

(reduce #'and (get-some-list))

Este es el mejor que he llegado con:

[11]> (defun my-and (x y) (and x y))
MY-AND

[12]> (reduce #'my-and '(T T T T T))
T

[13]> (reduce #'my-and '(T T T T NIL))
NIL

¿Por qué es "#" y" no válido? ¿Hay una manera más idiomática para hacer esto en Common Lisp?

¿Fue útil?

Solución

#'and no es válida porque and es una macro, no una función.

Se puede conseguir alrededor de tener que definir una función llamada, mediante el uso de un lambda:

(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t)

No hay acceso directo al igual que #' sin embargo.

Como alternativa también se puede utilizar every con la función de identificar como el predicado.

Otros consejos

Puede utilizar la función de cada:

(every #'identity '(T T T T T))  ->  T

y

(every #'identity '(T T T T NIL))  ->  NIL

Probablemente la forma más eficiente está utilizando BUCLE:

(loop for element in '(T T T T nil) always element)  ->  NIL

La ventaja es que no se necesitan más de las llamadas a funciones elementos de la lista.

#' es una macro de lectura que se expande en función durante leen la expresión. Así es #'and (FUNCIÓN Y).

función se describe aquí: http://www.lispworks.com/documentation/HyperSpec/Body/ s_fn.htm

función toma un nombre de función o una expresión lambda y devuelve el objeto de función correspondiente.

Y se define aquí: http://www.lispworks.com/documentation/HyperSpec/Body/ m_and.htm

Se dice que Y es una macro, no una función. La consecuencia es que (FUNCIÓN Y) no funciona, ya que la función necesita una función y no una macro para devolver el objeto función correspondiente. Como sepp2k describe en su respuesta, puede crear una función utilizando lambda y utilizar la macro Y dentro de esa función. Las macros no se puede pasar como los valores y más tarde se llamará a través de funcall o Aplicar. Esto sólo funciona con las funciones.

Esta solución se escribe como

(reduce (lambda (x y) (and x y)) (get-some-list))

LAMBDA es una macro que se expande (lambda (...) ...) en (function (lambda (...) ...)).

Así anterior es realmente:

(reduce (function (lambda (x y) (and x y))) (get-some-list))

que se puede escribir como

(reduce #'(lambda (x y) (and x y)) (get-some-list))
Se necesita

Función porque Common Lisp hace una diferencia entre el espacio de nombres para los valores y funciones. Reducir las necesidades para conseguir la función pasada como argumento por valor. Por lo que necesitamos para recuperar la función de la función de espacio de nombres - que es el propósito de FUNCIÓN. Cada vez que queremos pasar un objeto función, tenemos que conseguir que el espacio de nombres de función.

Por ejemplo en el caso de una función local:

(flet ((my-and (x y) (and x y)))
  #'my-and)

LAMBDA como una macro conveniencia que se expande en (function (LAMBDA ...)) se ha añadido durante el diseño de Common Lisp.

Se puede utilizar el símbolo 'Sharp-cita' sólo con las funciones ordinarias.

Note that only ordinary functions can be quoted with #’. It is an error to
quote a macro function or special function this way, or to quote a symbol with
#’ if that symbol does not name a function.

> #’if
Error: IF is not an ordinary function.

Common Lisp: Una Introducción a Cálculo Simbólico, página 202

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top