2016-01-05 14 views
6

Sto leggendo qualche codice Clojure al momento che ha un gruppo di valori non inizializzati come nil per un valore numerico in un record che viene passato in giro.Esiste un'alternativa idiomatica alla punzonatura zero in Clojure?

Ora molte delle librerie Clojure treat this as idiomatic. Ciò significa che è una convenzione accettata.

Ma porta anche a NullPointerException, perché non tutte le funzioni principali di Clojure possono gestire un nil come input. (Né dovrebbero).

Altre lingue hanno il concetto di Maybe o Option per delega il valore nel caso in cui esso è nullo, come un modo di mitigare il rischio NullPointerException. Questo è possibile in Clojure - but not very common.

È possibile eseguire alcuni trucchi con fnil ma non risolve tutti i problemi.

Un'altra alternativa è semplicemente impostare il valore non inizializzato su un simbolo come :empty-value per forzare l'utente a gestire questo scenario in modo esplicito in tutto il codice di gestione. Ma questo non è davvero un grande passo in avanti da nil - perché in realtà non si scoprono tutti gli scenari (nel codice di altre persone) fino al momento dell'esecuzione.

La mia domanda è: Esiste un'alternativa idiomatica alla punzonatura nullo in Clojure?

risposta

5

Non so se avete letto questo lispcast post su nil-punning, ma io credo che rende un buon caso per il motivo per cui è idiomatica e copre diverse importanti considerazioni che non ho visto citato in quelle altre domande in modo.

Fondamentalmente, nil è un di prima classe cosa in clojure. Nonostante il suo significato convenzionale intrinseco, lo è un valore appropriato e può essere trattato come tale in molti contesti e in un modo dipendente dal contesto. Questo lo rende più flessibile e potente di null nella lingua dell'host.

Ad esempio, una cosa del genere non sarà anche compilare in java:

if(null) { 
.... 
} 

Dove, come in clojure, (if nil ...) funzionano bene. Quindi ci sono molte situazioni in cui è possibile utilizzare nil in modo sicuro. Devo ancora vedere un codice java che non è limitato con codice come if(foo != null) { ... ovunque. Forse java 8's Optional cambierà questo.

Penso dove è possibile incorrere in problemi abbastanza facilmente è in scenari di interoperabilità java in cui avete a che fare con l'attuale null s. Una buona libreria wrapper di clojure può anche aiutarti a proteggerti da questo in molti casi, e il suo unico buon motivo è preferire uno sopra l'interoperabilità java diretta dove possibile.

Alla luce di questo, è possibile ri-considerare di combattere questa corrente. Ma dal momento che stai chiedendo delle alternative, ecco una che penso sia fantastica: prismatic's schema. Lo schema ha uno schema Maybe (e molti altri utili) e funziona molto bene in molti scenari. La libreria è abbastanza popolare e l'ho usata con successo.FWIW, è raccomandato nel recente libro clojure applied.

1

Esiste un'alternativa idiomatica alla punzonatura nullo in Clojure?

No. Come leeor spiega, nil-punning è idiomatico. Ma non è così diffuso come nel Common Lisp, dove (mi viene detto) una lista vuota equivale a zero.

Clojure utilizzato in questo modo, ma le funzioni CL che si occupano di elenchi corrispondono alle funzioni Clojure che trattano le sequenze in generale. E queste sequenze possono essere pigre, quindi c'è un premio nell'unificare le sequenze pigre con gli altri, in modo che qualsiasi pigrizia possa essere preservata. Penso che questa evoluzione sia avvenuta a proposito di Clojure 1.2. Rich lo ha descritto nel dettaglio here.

Se si desidera l'opzione/forse i tipi, dare un'occhiata alla libreria core.typed. Al contrario di Prismatic Schema, questo funziona in fase di compilazione.