Risposta breve ignora le regole di valutazione di default e fare non valutare l'espressione (simbolo o s-exp), passando lungo la funzione esattamente come digitato.
lungo Risposta: La regola di valutazione di default
Quando un regolare (verrò a che più tardi) la funzione viene richiamata, tutti gli argomenti passati ad esso vengono valutati.Ciò significa che è possibile scrivere questo:
(* (+ a 2)
3)
Che a sua volta valuta (+ a 2)
, valutando a
e 2. Il valore del simbolo a
viene cercato nel set vincolante variabile corrente, e poi sostituito. Dire a
è attualmente legato al valore 3:
(let ((a 3))
(* (+ a 2)
3))
ci saremmo (+ 3 2)
, + viene poi invocato il 3 e 2 cedendo 5. La nostra forma originale è ora (* 5 3)
cedendo 15.
Spiegare quote
Già!
OK. Come visto sopra, vengono valutati tutti gli argomenti di una funzione, quindi se si desidera passare il simbolo a
e non il suo valore, non si desidera valutarlo. I simboli Lisp possono raddoppiare entrambi come valori e marcatori in cui in altre lingue sarebbero state utilizzate stringhe, come le chiavi per le tabelle hash.
Questo è il punto in cui entra quote
. Si supponga di voler tracciare allocazioni di risorse da un'applicazione Python, ma piuttosto eseguire il tracciamento in Lisp. Avere il vostro Python app fare qualcosa di simile:
print "'("
while allocating:
if random.random() > 0.5:
print "(allocate %d)" random.randint(0, 20)
else:
print "(free %d)" % random.randint(0, 20)
...
print ")"
Dare un output simile a questo (leggermente prettyfied):
'((allocate 3)
(allocate 7)
(free 14)
(allocate 19)
...)
ricordare ciò che ho detto su quote
("tick") che causa la regola di default non applicare? Buona. Quello che succederebbe altrimenti è che i valori di allocate
e free
vengono cercati, e non lo vogliamo. Nel nostro Lisp, desideriamo fare:
(dolist (entry allocation-log)
(case (first entry)
(allocate (plot-allocation (second entry)))
(free (plot-free (second entry)))))
Per i dati di cui sopra, la seguente sequenza di chiamate di funzione sarebbe stato fatto:
(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)
ma che cosa circa list
?
Bene, a volte si do si desidera valutare gli argomenti. Supponiamo che tu abbia una bella funzione che manipola un numero e una stringa e che restituisca un elenco delle cose ... risultanti. Facciamo una falsa partenza:
(defun mess-with (number string)
'(value-of-number (1+ number) something-with-string (length string)))
Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))
Ehi! Non è quello che volevamo. Vogliamo in modo selettivo valutare alcuni argomenti e lasciare gli altri come simboli. Prova # 2!
(defun mess-with (number string)
(list 'value-of-number (1+ number) 'something-with-string (length string)))
Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)
Non Solo quote
, ma backquote
Molto meglio! Incidentalmente, questo modello è così comune nelle macro (principalmente), che esiste una sintassi speciale per fare proprio questo.Il backquote:
(defun mess-with (number string)
`(value-of-number ,(1+ number) something-with-string ,(length string)))
E 'come con quote
, ma con la possibilità di valutare in modo esplicito alcuni argomenti da anteponendo virgola. Il risultato è equivalente all'utilizzo di list
, ma se generi codice da una macro, spesso desideri solo valutare piccole parti del codice restituito, quindi il backquote è più adatto. Per gli elenchi più brevi, list
può essere più leggibile.
Ehi, hai dimenticato quote
!
Quindi, dove ci lascia? Oh, giusto, cosa fa effettivamente lo quote
? Restituisce semplicemente il suo argomento (s) non valutato! Ricordi cosa ho detto all'inizio riguardo alle funzioni regolari? Risulta che alcuni operatori/funzioni hanno bisogno di non valutare i loro argomenti. Ad esempio IF - non vorresti che il ramo else venisse valutato se non fosse stato preso, giusto? I cosiddetti operatori , insieme a macro, funzionano così. Gli operatori speciali sono anche l '"assioma" del linguaggio - insieme minimo di regole - su cui è possibile implementare il resto del Lisp combinandoli in modi diversi.
Torna quote
, però:
Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL
Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL
confronta con gli (su Steel-Bank Common Lisp):
Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING {A69F6A9}>:
The variable SPIFFY-SYMBOL is unbound.
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0]
perché non c'è spiffy-symbol
nell'ambito corrente!
Sommando su
quote
, backquote
(con virgola), e list
sono alcuni degli strumenti da utilizzare per creare elenchi, che non sono solo elenchi di valori, ma come hai visto possono essere utilizzati come leggero (non è necessario definire una struttura di dati struct
)!
Se desideri saperne di più, ti consiglio il libro di Peter Seibel Practical Common Lisp per un approccio pratico all'apprendimento del Lisp, se sei già interessato alla programmazione in generale. Alla fine, durante il tuo viaggio in Lisp, inizierai a usare anche i pacchetti. Il The Idiot's Guide to Common Lisp Packages di Ron Garret ti darà una buona spiegazione di quelli.
Happy hacking!
Come può essere valutato, ad esempio, esiste un comando 'unquote'? – William
@William Lisps ha una comoda funzione chiamata 'eval':' (print (eval '(+ 3 4)) '. Questo è ciò che rende Lisps così eccezionale: le liste sono codice e il codice è liste, quindi un programma Lisp può manipolarsi da solo. – darkfeline