2010-05-27 51 views
1

我想用一個宏來處理seq參數,但我不知道該怎麼做!宏如何處理像fn一樣的sql使用地圖

例如爲:

(defmacro create-table-def 
    [s] 
    `(let [ks# (keys (struct-map ~s)) 
     sql# (map (fn [p#] (str (name p#) " varchar(20) ")) ks#)] 
    (str "create-table " '~s " (" 
      (apply str (interleave seq# ", ")) ") "))) 

我有多個參數調用這個宏,但不能使用地圖(地圖創建表的高清PS)或減少,我應該怎麼辦處理。

我使用宏,因爲我想知道參數符號。

+0

請用四個空格縮進代碼或使用代碼按鈕(一個與1S編輯欄和0)來爲你做它。 – sepp2k 2010-05-27 09:53:40

+0

我不知道你是否更感興趣學習編寫宏或學習如何在Clojure中使用SQL。如果是後者,請查看clojure.contrib.sql,以及針對您問題中的示例,特別是create-table函數。 – 2011-04-23 01:22:59

回答

0

我想出了這個版本,是相當接近的版本:

(defmacro create-table-def [table-name key-val-map] 
    (let [sql-part1 (vector "create table " 
     (name table-name) 
     "(") 
sql-pre-part2 (apply vector 
     (map #(str (name (first %)) 
    " " 
    (second %)) 
     key-val-map)) 
sql-part2 (butlast (interleave sql-pre-part2 (repeat ", "))) 
sql-part3 [");"]] 
    (apply str (concat sql-part1 sql-part2 sql-part3)))) 

(create-table-def my-table {foo "varchar(20)" bar "int"}) 
;"create table my-table(foo varchar(20), bar int);" 

如果你真的需要一個序列傳給你可以這樣做:

(defmacro create-table-def2 [[name & pairs]] 
    `(create-table-def ~name ~(apply array-map pairs))) 

(create-table-def2 [my-table foo "varchar(20)" bar "int"]) 
;"create table my-table(foo varchar(20), bar int);" 

或者只是作爲直接參數:

(defmacro create-table-def3 [name & pairs] 
    `(create-table-def ~name ~(apply array-map pairs))) 

(create-table-def3 my-table foo "varchar(20)" bar "int") 
;"create table my-table(foo varchar(20), bar int);" 

更直接關注解決方案,但是,(ab)使用打印的repr地圖的esentation:下一次

(use '[clojure.contrib.string :as str-utils]) 
(defmacro table-def [tname & things] 
    (str-utils/join " " 
    ["create-table" (name tname) "(" 
    (str-utils/drop 1 
      (str-utils/chop 
       (print-str (apply array-map things)))) 
    ");"])) 
(table-def my-table foo "varchar(20)" bar "int") 
;"create-table my-table (foo varchar(20), bar int);" 
相關問題