Domanda

Dato un elenco di valori, voglio ridurre l'elenco a T se tutti gli elementi non sono NIL, NIL se non. Questo mi dà un errore:

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

Come fa questo:

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

Questo è il migliore che è venuta in mente:

[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

Perché è "# 'e" non valido? C'è un modo più idiomatico per fare questo in Common Lisp?

È stato utile?

Soluzione

#'and non è valido perché and è una macro, non una funzione.

E 'possibile andare in giro dover definire una funzione denominata, utilizzando un lambda:

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

Non c'è scorciatoia come #' però.

In alternativa si può anche utilizzare every con la funzione di identificare come il predicato.

Altri suggerimenti

È possibile utilizzare la funzione OGNI:

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

e

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

Probabilmente il modo più efficiente sta usando LOOP:

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

Il vantaggio è che non sono necessari richiami di funzioni oltre gli elementi della lista.

#' è una macro lettura che si espande in funzione Durante leggere l'espressione. Così #'and è (FUNZIONE E).

funzione è descritta qui: http://www.lispworks.com/documentation/HyperSpec/Body/ s_fn.htm

accetta un nome di funzione o un'espressione lambda e restituisce l'oggetto funzione corrispondente.

ed è definito qui: http://www.lispworks.com/documentation/HyperSpec/Body/ m_and.htm

Si dice che E è una macro, non una funzione. La conseguenza è che (FUNZIONE E) non funziona, poiché la funzione necessita di una funzione e non una macro per restituire l'oggetto funzione corrispondente. Come sepp2k descrive nella sua risposta, è possibile creare una funzione tramite LAMBDA e utilizzare la macro e dentro quella funzione. Le macro non può essere passato come valori e poi essere richiamato tramite funcall o Applica. Questo funziona solo con le funzioni.

Questa soluzione è scritta come

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

LAMBDA è una macro che si espande in (lambda (...) ...) (function (lambda (...) ...)).

di cui sopra è in realtà:

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

, che può essere scritto come

(reduce #'(lambda (x y) (and x y)) (get-some-list))
è necessario

FUNZIONE perché Common Lisp fa la differenza tra lo spazio dei nomi per i valori e le funzioni. RIDURRE esigenze per ottenere la funzione passata come argomento per valore. Quindi abbiamo bisogno di recuperare la funzione dalla funzione dello spazio dei nomi - che è lo scopo della funzione. Ogni volta che vogliamo passare un oggetto funzione, abbiamo bisogno di ottenere dalla funzione di spazio dei nomi.

Ad esempio nel caso di una funzione locale:

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

LAMBDA come vantaggio macro che si espande in (function (LAMBDA ...)) è stato aggiunto durante la progettazione del Common Lisp.

È possibile utilizzare il simbolo 'sharp-quote' solo con le funzioni ordinarie.

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: A Gentle Introduction al calcolo simbolico, pagina 202

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top