2012-12-25 7 views
6

C'è qualche modo per contrassegnare un simbolo come obsoleto in Clojure?Obsoleto-ing simboli in Clojure

Potrei usare qualcosa di simile da Lein che funziona bene.

https://github.com/technomancy/leiningen/blob/1.x/src/leiningen/core.clj#L13

Ma l'emette solo il suo avvertimento quando viene chiamata una funzione. Mi piacerebbe davvero che il compilatore lo rilevasse al momento della compilazione del codice, piuttosto che quando viene chiamato.

Naturalmente, ho potuto solo non definire il simbolo, che il compilatore sarebbe quindi prendere up, ma questo mi priva della capacità di fornire tutte le informazioni, come ad esempio il motivo per cui, o quando il simbolo è stato deprecato .

Tutto questo è per una DSL in cui la deprecazione e l'obsolescenza dei termini avverranno a un ritmo ragionevole.

+1

Invece di ridefinire la funzione come un'altra funzione, ridefinirla come una macro che emette un avviso mentre viene espansa in fase di compilazione. – Barmar

+0

@Barmar Che rende impossibile l'utilizzo come argomento o letterale. Idea terribile Invece, basta forzare l'avviso durante l'espansione della macro defdeprecated. (Il che ovviamente significa che l'avvertimento si verifica solo durante la compilazione della libreria, che potrebbe non essere ciò che si desidera). – Cubic

+0

@cubic No, anche questo è sbagliato. Il punto è di avvertire quando un'applicazione client _utilizza_ la funzione obsoleta, non quando la libreria è compilata. Penso che ottenere ciò che è veramente desiderato avrà un supporto speciale nel compilatore Clojure. – Barmar

risposta

1

C'è già qualcosa nei commenti sull'uso delle macro, ma come qualcuno ha notato questo preclude l'utilizzo della funzione come un HOF. Puoi aggirare questo, anche se può darsi che la cura non sia peggiore della malattia. Per esempio, immaginate la vostra funzione è

(defn foo* [x y] (+ x y)) 

Poi invece di scrivere

(defmacro foo [x y] (warn) `(foo* x y)) 
(foo 1 2) 
(map foo [5 6] [7 8]) 

È possibile effettuare la macroexpansion ritorno una funzione, che ovviamente può essere utilizzato come qualsiasi altro:

(defmacro foo [] (warn) `foo*) 
((foo) 1 2) 
(map (foo) [5 6] [7 8]) 

Probabilmente non vale l'imbarazzo, ma fornisce un modo per lamentarsi ogni volta che la funzione deprecata viene utilizzata pur mantenendo la possibilità y dell'utilizzo HOF.

0

Dipende davvero da come è stato progettato il DSL. Se è possibile progettare il DSL in modo che ogni modulo deve essere avvolto in una chiamata go o qualcosa di simile allora si potrebbe scrivere questo go macro che fa qualcosa di simile:

  1. macroexpand-all (da clojure.walk) alla forma passata
  2. Utilizzare postwalk (da clojure.walk) sul modulo restituito sopra e controllare se uno qualsiasi dei simboli incontrati è deprecato probabilmente guardando un elenco globale di simboli deprecati. Potrebbe essere necessario fare resolve sui simboli per ottenere il nome qualificato dello spazio dei nomi del simbolo.
  3. Se viene trovato un simbolo deprecato, il messaggio di stampa.
  4. Restituisce il modulo di input così com'è.

Questa macro go può quindi essere utilizzata per altre pre-elaborazioni del DSL poiché questo è il punto di ingresso per l'esecuzione DSL.

NOTA: potrebbe essere necessario trovare una soluzione in cui l'utente utilizza lo stesso nome per il proprio simbolo da uno dei simboli deprecati, ma anche in questo caso potrebbe non essere necessario in base al progetto DSL.