2013-04-24 9 views
6

Desidero che il mio programma clojure abbia una directory di script che può essere eseguita - ciascuno di questi script è il codice del clojure che eseguo con il file di caricamento. Questo accade in un futuro in modo che lo script venga eseguito in una propria discussione.Gestione delle eccezioni all'interno di futures e file di carico

Il problema è che non vedo mai messaggi di errore dagli script. Se lo script fallisce, non c'è modo di sapere cosa è andato storto. Presumo questo perché non c'è alcuna gestione delle eccezioni all'interno del thread del futuro. Posso mettere la gestione delle eccezioni nella sceneggiatura, come qui di seguito, e funziona:

;; script code  
(try 

(println (/ 10 0)) 

(catch Exception e 
    (println "Exception: " (.getMessage e)))) 

Tuttavia, preferisco mettere l'eccezione la gestione di un livello superiore a quello, tutto il load-file, in modo che I don' t devono avere la gestione delle eccezioni nello script stesso:

(defn handleexes [f] 
    (try 
    (f) 
    (catch Exception e 
     (println "exception: " (.getMessage e))))) 

(defn start-script-play [name] 
    (println "starting script: " name) 
    (let [f (future (handleexes (load-file (str "./scripts/" name))))] 
    (swap! scripts (fn [s] (assoc s name f))))) 

Così sto chiamando il file di caricamento all'interno di handless. questo non funziona, soprattutto. Funziona quando eseguo uno script che contiene il proprio gestore di eccezioni, come sopra! Senza il gestore di eccezioni nella sceneggiatura, niente. Wierd.

Ok bene comunque la mia domanda è che diavolo sta succedendo qui?

  • eccezioni non gestite in futuro?
  • perché non vengono rilevate eccezioni quando si verificano all'interno del file di caricamento?
  • Come posso rilevare eccezioni in questa situazione?

risposta

6

Non sembrano essere mai dereferenziazione (sia con deref o @) il future si sta producendo nel tuo esempio.

Se viene generata un'eccezione in un futuro, tentare di dereferenziare tale futuro comporterà il lancio di java.util.concurrent.ExecutionException. Questa eccezione avvolgerà tutto ciò che è stato lanciato in futuro.

(try 
    (future (/ 10 0)) 
    "done" 
    (catch Exception e 
    (str "caught " e))) 

;=> "done" 


(try 
    @(future (/ 10 0)) 
    "done" 
    (catch Exception e 
    (str "caught " e))) 

;=> "caught java.util.concurrent.ExecutionException: java.lang.ArithmeticException: Divide by zero" 
+0

Interessante --- ma per me questo non è utile poiché non ho mai intenzione di dereferenziare il futuro. Sto eseguendo gli script esclusivamente per gli effetti collaterali e gli script potrebbero andare in loop per sempre. In quel caso il filo che deruba il futuro bloccherà per sempre. Immagino di poter fare un altro futuro per controllare il primo futuro! Forse i futures non sono la soluzione da usare qui. – Bzzt

+4

Gli agenti potrebbero darti di più quello che stai cercando, in quel caso. Tra le altre cose, ti permettono di specificare un gestore di errori arbitrario. http://clojure.org/agents – dfreeman