2011-08-17 24 views
8

Tôi đã tự hỏi liệu có thể tải mã có trong tệp nguồn Clojure .clj dưới dạng danh sách mà không biên dịch nó hay không.Sửa đổi tệp mã nguồn Clojure trong clojure

Nếu tôi có thể tải tệp .clj dưới dạng danh sách, tôi có thể sửa đổi danh sách đó và in lại dễ dàng vào cùng một tệp để có thể tải lại.

(Có lẽ đây là một ý tưởng tồi.) Có ai biết nếu điều này là có thể không?

+1

Đó không phải là một ý tưởng tồi chút nào. Nó có thể được sử dụng cho những thứ như phân tích mã và rfactoring. – ivant

Trả lời

1

Một ví dụ đơn giản hơn một chút:

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 

đâu slurp mang đến cho bạn một chuỗi, read-string mang đến cho bạn một hình thức un-đánh giá, và load-string mang đến cho bạn kết quả của việc đánh giá hình thức.

7

Nó không phải là một ý tưởng tồi, nó là một trong những thuộc tính chính của lisp, code là dữ liệu. bạn có thể đọc tệp clj dưới dạng danh sách bằng cách sử dụng chuỗi sửa đổi và ghi lại.

 

(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))))) 
 

Điều này tự đọc và chuyển đổi giá trị boolean và ghi lại.

+1

Thêm parens xung quanh văn bản slurped không phải là một ý tưởng tốt. Sử dụng 'đọc' nhiều lần cho đến khi tập tin được tiêu thụ sạch hơn và mạnh mẽ hơn. – kotarak

+0

Tuyệt! Tôi sẽ thử cái này! Cảm ơn bạn! – sneilan