Perché usare #' con lambda?
Domanda
Perché dovrei usare #' insieme a lambda?Di solito è scritto in questo modo, quindi immagino che sia una buona forma.Ma queste righe mi sembrano uguali:
> (mapcar #'(lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)
> (mapcar (lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)
Qualcuno vuole illuminare un principiante sulla differenza?
Soluzione
#'
è una scorciatoia per function
, che restituisce un puntatore a una funzione (invece di applicarlo). lambda
restituisce una funzione, ed è solito per voler un puntatore a quella funzione. Dal momento che questo è così comune, v'è anche una macro (nello spazio variabile) che lo fa per te, che si chiama lambda
pure. Entrambe le linee di codice sono identici.
Che è meglio si riduce al Lisp-1 / Lisp-2 dibattito : in Common Lisp è possibile effettuare una, grazie alla macro. Come sempre, essere coerenti.
Altri suggerimenti
È diverso nei vari dialetti Lisp.Quanto segue utilizza Common Lisp:
Primo #' è una notazione breve per (funzione ...).Quindi i seguenti sono diversi solo testualmente, ma Common Lisp li legge allo stesso modo:
#'(lambda (x) (* x 2))
E
(function (lambda (x) (* x 2)))
#' è una readmacro e si trasforma quando il codice Lisp viene letto dal sistema Lisp.
Se Lisp valuta
(function (lambda (x) (* x 2)))
IL Il sistema Lisp crea un oggetto funzione e FUNCTION lo restituisce come valore.
Quindi, ogni volta che hai bisogno di una funzione come valore, devi scriverla in questo modo.Una funzione come valore è necessaria quando vuoi passarla ad un'altra funzione come argomento, quando vuoi restituirla da una funzione o quando vuoi memorizzarla in una variabile.Esempi:
(map #'(lambda (x) (* x 2)) '(1 2 3))
(defun (y) #'(lambda (x) (* x y)))
(defparameter *twice-fn* #'(lambda (x) (* x 2)))
Ora, cos'è (lambda (x) (* x 2)) ?
Sono due cose diverse a seconda del contesto.
Espressione Lambda
L'espressione lambda può essere utilizzata al posto del nome di una funzione:
(function foo) and (function (lambda (x) (* x 2)))
E
(foo 17) and ((lambda (x) (* x 2)) 17)
I due precedenti sono la sintassi Common Lisp legale.Lì è possibile utilizzare direttamente un'espressione lambda.
Si noti che le due forme seguenti lo sono illegale nel Lisp comune:
(#'(lambda (x) (* x 2)) 17) ; illegal in Common Lisp
(function #'(lambda (x) (* x 2))) ; illegal in Common Lisp
Macro
Durante il processo di standardizzazione del Common Lisp è stata aggiunta una macro LAMBDA (non faceva parte della prima descrizione, CLtL1, del Common Lisp).Rende possibile scrivere codice leggermente più breve.Esempio:
(lambda (x) (* x 2))
Nel caso sopra LAMBDA è una macro.Durante la macroespansione verrà esteso a:
(function (lambda (x) (* x 2)))
Ricorda che nella forma FUNZIONE sopra, il lambda interno fa parte di un'espressione lambda, denota la funzione e non verrà espanso.
Quindi, ora i tre esempi di cui sopra possono essere scritti come:
(map (lambda (x) (* x 2)) '(1 2 3))
(defun (y) (lambda (x) (* x y)))
(defparameter *twice-fn* (lambda (x) (* x 2)))
È leggermente più corto, sembra un po' meno ingombrante e sembra leggermente più simile al codice Scheme.Sembra semplicemente un po' migliore per i programmatori abituati a leggere e scrivere codice Scheme.
Riepilogo
a) (function (lambda (x) (* x 2))) è il modo "vero" di scrivere codice che restituisce una funzione come valore.
b) #'(lambda (x) (* x 2)) è una notazione più breve di cui sopra
c) (lambda (x) (* x 2)) è ancora più breve, ma utilizza l'espansione macro per creare la forma di a).