Ricerca…


S-Expression

Un'espressione in Scheme è ciò che verrà eseguito. Un'espressione S, come di solito viene chiamata inizia con a ( e termina con a ) . Il primo membro dell'espressione è ciò che verrà eseguito. Il seguente membro dell'espressione sono i parametri che verranno inviati all'espressione durante la valutazione dell'espressione.

Ad esempio aggiungendo numeri:

(+ 1 2 3)

In questo caso, + è un simbolo per una funzione di aggiunta che richiede più parametri. 1 , 2 e 3 vengono inviati alla funzione + .

S-Expression può contenere S-Expressions come parametri come mostrato nel seguente esempio:

(if (< x y)
  x
  y)

Che può essere letto come se x fosse minore di y restituisca x altrimenti ritorna y . In questo esempio valutiamo l'espressione della condizione, a seconda del valore risolto, verrà restituito x o y. Potrebbe essere valutato a questo

(if #t x y)
x
(if #f x y)
y

Un esempio meno ovvio per i principianti è di avere un'espressione S come parte del primo membro di una S-Expression. In questo modo, possiamo cambiare il comportamento di un metodo cambiando la funzione che verrà chiamata senza dover creare rami con gli stessi parametri. Ecco un rapido esempio di un'espressione che può aggiungere o sottrarre numeri se x è sotto y.

((if (< x y) + -) 
  1 2 3)

Se x è sotto y , l'espressione sarà valutata come:

(+ 1 2 3)
6

altrimenti

(- 1 2 3)
-4

Come potete vedere, Scheme consente al programmatore di creare una parte di codice complessa mentre fornisce al programmatore gli strumenti per prevenire la duplicazione del codice. In altre lingue potremmo vedere lo stesso esempio scritto come tale:

(if (<xy) (+ 1 2 3) (- 1 2 3))

Il problema con questo metodo è che duplichiamo molto codice mentre l'unica cosa che cambia è il metodo che viene chiamato. Questo esempio è abbastanza semplice ma con più condizioni potremmo vedere molte linee simili duplicate.

Lasciare macro semplice

Le espressioni let in scheme sono in effetti macro. Possono essere espressi con lambda. Un semplice let potrebbe assomigliare a questo:

(let ((x 1) (y 2))
  (+ x y))

Restituirà 3 come viene restituito il valore dell'ultima espressione del corpo let. Come puoi vedere, un'espressione let è in realtà in esecuzione qualcosa. Se traduciamo questa parte di codice con lambdas, otterremmo qualcosa del genere:

((lambda (x y) (+ x y)) 1 2)

Qui possiamo vedere che stiamo chiamando l'anonymous lambda con 1 e 2 direttamente. Quindi il risultato in questo caso è anche 3.

Con questo in mente, capiamo che un'espressione let è composta da 2 parti. Ha dei parametri e un corpo come un lambda, ma la differenza è che lascia che le espressioni vengano chiamate dopo la loro valutazione.

Per spiegare come un'espressione let funziona da una vista astratta a una vista concreta, sarebbe simile a questa.

(let params body ...)
(let (param1 param2 ...) body ...)
(let ((p1 val1) (p2 val2) ...) body ...)

I parametri sono una lista di coppie di (name value) da utilizzare nel corpo del let .

Perché usare lasciare espressione?

Le espressioni sono particolarmente utili per memorizzare le variabili in un metodo proprio come le inizializzazioni della variabile in c come i linguaggi. È favorevole all'uso di define perché fuori dall'espressione let, le variabili sono sparite ... L'uso di un define è in realtà l'aggiunta di una variabile all'ambiente di esecuzione corrente. Le variabili aggiunte all'ambiente globale non possono essere rimosse. Lascia che l'espressione sia sicura da usare ovunque. Può anche essere usato per ghostare le variabili senza toccare gli ambiti genitore.

Per esempio:

(let ((x 1))
  (let ((x 2) (y x))
    (display x)
    (display y))
  (display x))

Stamperà:

2
1
1

In questo caso, x è definito con 1, quindi ghostato dalla x nella seconda let con il valore 2 . La variabile y viene iniziata con il valore x dell'ambito principale. Dopo che l'espressione let interna è stata eseguita, mostra il valore iniziale di x con 1. L'espressione inner let non ha modificato il valore dell'ambito genitore.

Ogni volta che hai bisogno di inizializzare le variabili, dovresti usare let espressioni come questa:

(let (
  (user (get-current-user session))
  (db (get-current-db session))
  (ids (get-active-ids session))
  )
  (mark-task-completed db user ids)
  (change-last-logged db user)
  (db-commit db))

Qui in questo esempio, le variabili vengono inizializzate e utilizzate più volte nel blocco di codice. E quando l'espressione let è terminata, le variabili vengono automaticamente liberate poiché non sono più necessarie.

Sintassi punteggiata per coppie

Esiste una sintassi particolare che ci consente di scrivere cons cella in un modo più compatto rispetto all'uso del cons constr.

Una coppia può essere scritta come tale:

'(1 . 2) == (cons 1 2)

La grande differenza è che possiamo creare pairs usando la citazione. In caso contrario, Scheme creerebbe un elenco appropriato (1 . (2 . '())) .

La sintassi del punto forza l'espressione ad avere solo 2 membri. Ogni membro può essere di qualsiasi tipo, incluse le coppie.

'(1 . (2 . (3 . 4)))
> (1 2 3 . 4)

Si noti che l'elenco improprio dovrebbe essere visualizzato con un punto alla fine per mostrare che il cdr dell'ultima coppia della lista non è la lista vuota '() .

Questo modo di mostrare le liste è un po 'confuso poiché la seguente espressione non sarebbe espressa come ci si aspetterebbe.

'((1 . 2) . ( 3 . 4))
> ((1 . 2) 3 . 4)

Poiché la lista di solito salta il . , il primo argomento della lista sarebbe (1 . 2) , il secondo argomento sarebbe 3 ma poiché l'elenco è errato, l'ultimo . viene mostrato per mostrare che l'ultimo elemento della lista non è '() . Anche se si pensa, i dati sono mostrati in un modo diverso, i dati interni sono come è stato creato.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow