Изменить файл исходного кода Clojure в clojure - PullRequest
8 голосов
/ 17 августа 2011

Мне было интересно, можно ли загрузить код, содержащийся в исходном файле Clojure .clj, в виде списка без его компиляции.

Если я могу загрузить файл .clj в виде списка, я могу изменить этот список и распечатать его обратно в тот же файл, который затем можно загрузить снова.

(Может быть, это плохая идея.) Кто-нибудь знает, возможно ли это?

Ответы [ 3 ]

7 голосов
/ 17 августа 2011

Это неплохая идея, это одно из основных свойств lisp, код - данные. Вы можете прочитать файл clj в виде списка, используя read-string, изменить его и записать обратно.


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

Это считывает само себя, переключает логические значения и записывает их обратно.

1 голос
/ 11 июня 2013

Немного более простой пример:

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

Где slurp дает вам строку, read-string дает вам не оцененную форму, а load-string дает вам результат оценки формы.

0 голосов
/ 25 июля 2017

Есть библиотека с именем rewrite-clj , которая может такого рода вещи.

https://github.com/xsc/rewrite-clj

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...