2011-08-17 16 views
8

Me preguntaba si es posible cargar el código contenido en un archivo fuente Clojure .clj como una lista, sin compilarlo.Modificar archivo de código fuente Clojure en clojure

Si puedo cargar un archivo .clj como una lista, puedo modificar esa lista e imprimirla de nuevo en el mismo archivo que luego se puede volver a cargar.

(Quizás esta es una mala idea.) ¿Alguien sabe si esto es posible?

+1

No es una mala idea en absoluto. Se puede usar para cosas como análisis de código y factorización. – ivant

Respuesta

1

Un ejemplo un poco más simple:

user=> (def a '(println (+ 1 1))) ; "'" escapes the form to prevent immediate evaluation 
#'user/a 
user=> (spit "test.code" a) ; write it to a file 
nil 

user=> (def from-file (read-string (slurp "test.code"))) ; read it from a file 
#'user/from-file 
user=> (def modified (clojure.walk/postwalk-replace {1 2} from-file)) ; modify the code 
#'user/modified 
user=> (spit "new.code" modified) ; write it back 
nil 
user=> (load-string (slurp "new.code")) ; check it worked! 
4 
nil 

Dónde slurp le da una cadena, read-string le da una forma un-evaluado y load-string le da el resultado de evaluar la forma.

7

No es una mala idea, es una de las principales propiedades de lisp, el código es de datos. puede leer el archivo clj como una lista usando read-string modifíquelo y escríbalo de nuevo.

 

(ns tmp 
    (:require [clojure.zip :as zip]) 
    (:use clojure.contrib.pprint)) 

(def some-var true) 

;;stolen from http://nakkaya.com/2011/06/29/ferret-an-experimental-clojure-compiler/ 
(defn morph-form [tree pred f] 
    (loop [loc (zip/seq-zip tree)] 
    (if (zip/end? loc) 
     (zip/root loc) 
     (recur 
     (zip/next 
     (if (pred (zip/node loc)) 
      (zip/replace loc (f (zip/node loc))) 
      loc)))))) 

(let [morphed (morph-form (read-string (str \((slurp "test.clj")\))) 
          #(or (= 'true %) 
           (= 'false %)) 
          (fn [v] (if (= 'true v) 
            'false 
            'true)))] 
    (spit "test.clj" 
     (with-out-str 
      (doseq [f morphed] 
      (pprint f))))) 
 

Esto se lee a sí mismo y alterna los valores booleanos y los escribe de nuevo.

+1

Agregar parens alrededor del texto sorbido no es una buena idea. El uso de 'read' repetidamente hasta que se consuma el archivo es más limpio y más robusto. – kotarak

+0

¡Genial! ¡Voy a intentar esto! ¡Gracias! – sneilan