2011-11-18 3 views
12

Sto riscontrando alcuni problemi nel capire come utilizzare il modulo "let". Nell'esempio seguente, vorrei legare localmente il valore "cols" per lavorarci in seguito nella funzione. Quello che sto notando, tuttavia, è che se uso "let" la funzione sel-opt-tmp restituirà un valore nullo anziché una lista.Clojure: lasciare scope e funzione valore restituito

(defn sel-opt-tmp [] 
    (let [cols "test"])) 

(prn (sel-opt-tmp)) 

* Il codice sopra riportato restituisce un valore nullo.

Capisco che "let" leghi solo un valore nell'ambito di una funzione, quello che non so è se esiste un modo per passare il valore fuori dall'ambito di let. Forse c'è qualcosa come "ritorno" di cui non sono a conoscenza? O questo è semplicemente un cattivo design e in questo caso non dovrei assolutamente usare il binding (questo tende a creare lunghe catene di funzioni che sono difficili da leggere anche se)?

+2

Il modulo 'let' restituisce implicitamente l'ultima espressione che contiene, che nel tuo caso è l'invisibile' nil'. Devi usare 'cols' nel corpo del form' let' per averlo restituito. – seh

+0

'" let "lega solo un valore nell'ambito di una funzione - non è del tutto vero. 'Let's può apparire più ovunque, e l'ambito dei nomi associati è l'espressione' let'. –

risposta

17

Restituisce nulla perché il contenuto dell'istruzione let è vuoto (o nullo). Prova:

(let [cols "test"] cols)

che restituirà il valore di cols. Come dice seh, una dichiarazione let valuta il valore della sua ultima sottoespressione.

+1

Un form 'let' è esso stesso un'espressione, che * valuta * il valore della sua ultima sotto-espressione! –

+0

Grazie Matt, ho aggiornato il testo. Non so perché non l'ho fatto prima ... –

3

Non c'è alcun problema con il passaggio di valori al di fuori dell'ambito come si menziona. L'associazione cols è in vigore solo nell'ambito, ma la durata del valore di (:ks cols) non è limitata. (Ecco perché si dispone di garbage collection: è possibile restituire valori che puntano ai dati e i dati rimangono attivi finché ci sono riferimenti.)

Se si ottiene nil dalla funzione, è probabile che lo sia cols non avere una chiave :ks ... o in effetti potrebbe non essere una mappa. Poiché cols è il risultato di filter, è una sequenza e quando la parola chiave :ks viene utilizzata come funzione, restituisce nil per le non raccolte. Per proteggersi da questo tipo di bug, potrebbe essere una convenzione utile scrivere sempre (cols :ks) anziché (:ks cols) in modo da ottenere un errore quando ciò che pensi sia una mappa è un'altra cosa.

+0

Ciao, ho fatto un piccolo test e ancora ottenendo un nulla. Il codice è sopra. – kfk