Clojure: Кто-нибудь создал инструмент для визуализации древовидной структуры вашего кода? - PullRequest
0 голосов
/ 05 мая 2018

Я изучаю Clojure (мой первый LISP) и изучаю идею «кода как данных», присущую LISP. Мне любопытно, кто-нибудь когда-либо создавал инструмент, который будет читать программу и создавать реферат синтаксическое дерево в визуализаторе для вас - возможно, расширение до и после макроса?

Под этим я подразумеваю графическое изображение дерева в чем-то вроде SVG.

1 Ответ

0 голосов
/ 05 мая 2018

Действительно, все, что вам нужно сделать, это ' (цитата) форма, чтобы получить АСТ этого. В этом красота губ. Скажем, у вас есть стандартная every? функция:

(defn every?
  "Returns true if (pred x) is logical true for every x in coll, else
   false."
  {:tag Boolean
   :added "1.0"
   :static true}
  [pred coll]
  (cond
     (nil? (seq coll)) true
     (pred (first coll)) (recur pred (next coll))
     :else false))

Просто процитируйте его, чтобы получить вложенный список символов:

; Notice the quote at the start!
'(defn every?
   "Returns true if (pred x) is logical true for every x in coll, else
   false."
   {:tag Boolean
    :added "1.0"
    :static true}
   [pred coll]
   (cond
      (nil? (seq coll)) true
      (pred (first coll)) (recur pred (next coll))
      :else false))
=>
(defn
 every?
 "Returns true if (pred x) is logical true for every x in coll, else\nfalse."
 {:tag Boolean, :added "1.0", :static true}
 [pred coll]
 (cond (nil? (seq coll)) true (pred (first coll)) (recur pred (next coll)) :else false))

Вы можете немного улучшить его для визуализации, используя стандартную функцию clojure.pprint/pprint (отступ указывает на вложение):

(clojure.pprint/pprint
  '(defn every?
     "Returns true if (pred x) is logical true for every x in coll, else
   false."
     {:tag Boolean
      :added "1.0"
      :static true}
     [pred coll]
     (cond
        (nil? (seq coll)) true
        (pred (first coll)) (recur pred (next coll))
        :else false)))
(defn
 every?
 "Returns true if (pred x) is logical true for every x in coll, else\n   false."
 {:tag Boolean, :added "1.0", :static true}
 [pred coll]
 (cond
  (nil? (seq coll))
  true
  (pred (first coll))
  (recur pred (next coll))
  :else
  false))

И вы можете получить представление расширения после макроса, передав туда вызов macroexpand:

(clojure.pprint/pprint
  (macroexpand
    '(defn every?
       "Returns true if (pred x) is logical true for every x in coll, else
   false."
       {:tag Boolean
        :added "1.0"
        :static true}
       [pred coll]
       (cond
          (nil? (seq coll)) true
          (pred (first coll)) (recur pred (next coll))
          :else false))))
(def
 every?
 (clojure.core/fn
  ([pred coll]
   (cond
    (nil? (seq coll))
    true
    (pred (first coll))
    (recur pred (next coll))
    :else
    false))))

Если вы ищете что-то большее, просто зацитировать некоторый код, а затем рекурсивно выполнить поиск по нему. Вы можете изменить его в любой формат, который вы хотите.

...