如何使用defmacro简化一些代码

use*_*464 1 lisp macros clojure

我写了两个像这样的函数,但是你看到它们中的大多数都是相同的,所以我想编写一个宏来简化它们.

我理解教科书中的简单宏示例,但我不知道如何编写自己的.

这是我的代码:

 (defn load-dict
       ;  "Load database from a txt file previous saved"
       [fname]
       (with-open [rdr (io/reader fname)]
                  (doseq [line (line-seq rdr)]
                         (println line)
                         (def vvv (clojure.string/split line #"\s"))
                         ;(println (str "count of vvv is " (count vvv)))
                         (if (< 1 (count vvv))
                           (add- dict (gen-word (nth vvv 0) (nth vvv 2) (nth vvv 1))))
                         )))
 (defn load-article
       ;  "Load article from a txt file"
       [fname]
       (with-open [rdr (io/reader fname)]
                  (doseq [line (line-seq rdr)]
                         (println line)
                         (def vvv (clojure.string/split line #"\s"))
                         ;(println (str "count of vvv is " (count vvv)))
                         (if (< 1 (count vvv))
                           (add- article vvv ))
                         )))
Run Code Online (Sandbox Code Playgroud)

我应该写一个像:

(defmacro load- [target fname &expr)
  `(... 
    (add- ~target expr)))
Run Code Online (Sandbox Code Playgroud)

我其实不知道怎么写这样的宏.我只是讨厌重复的代码.

PS,拖曳功能正常.我不关心变量这是代码的一部分.

Leo*_*hin 5

我会使用let块而不是def.使用def将绑定var并在命名空间中定义vvv.实际上并不需要宏.您可以像这样简化代码:

(defn load-from
   "Load database from a txt file previous saved"
   [fname load-fn]
   (with-open [rdr (io/reader fname)]
              (doseq [line (line-seq rdr)]
                     (println line)
                     (let [vvv (clojure.string/split line #"\s")]
                       (when (< 1 (count vvv))
                         (load-fn vvv))))))
Run Code Online (Sandbox Code Playgroud)

并像这样调用它

(load-from "myfile.txt" #(add- dict (apply gen-word (take 3 %))))
(load-from "myfile.txt" #(add- article %))
Run Code Online (Sandbox Code Playgroud)