2013-04-08 69 views
1

我試圖用其中宏函數:Clojure科爾馬:如何使用函數中的宏?

(defentity student 
    (pk :id) 
    (table :student) 
    (entity-fields :id :name :age :class) 
    (database prod)) 

(defn query-student [cond] 
    (select student 
    (where cond))) 

我測試一下:

(select student 
    (where {:age [> 13]})) 

(query-student '{:age [> 13]}) 

它看起來不錯,但這個

(select student 
    (where (or {:age [> 13]} {:class [in ["1" "2" "3"]]}))) 

(query-student '(or {:age [> 13]} {:class [in ["1" "2" "3"]]})) 

不起作用!

Failure to execute query with SQL: 
SELECT "student".* FROM "student" WHERE (or {:age [> 13]} {:class [in ["1" "2" "3"]]}) ::  [] 
PSQLException: 
Message: ERROR: syntax error at or near "or" 
    Location:42 
SQLState: 42601 
Error Code: 0 
PSQLException ERROR: syntax error at or near "or" 
    Location:42 org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse (QueryExecutorImpl.java:2101) 

我想知道爲什麼?有問題?

回答

2

在科爾馬,where是一個宏,因此你的第二個例子傳遞一個列表文字給它,而不是給宏評估表單的機會。

試着改變你的query-student功能於宏而是沿着這些線路

(defmacro query-student [cond] 
    `(select student 
    (where ~cond))) 

作爲額外的獎勵,你不會需要引用使用宏時的形式:

(query-student (or {:age [> 13]} {:class [in ["1" "2" "3"]]}))

希望這有助於。

+0

感謝您的幫助。將功能更改爲宏是好的。但是我想在一個文件中保存(或{:age [> 13]} {:class [in [「1」「2」「3」]]}),然後在執行前讀取它。我是否可以將數據'(或{:age [> 13]} {:class [in [「1」「2」「3」]]})轉換爲? – Barton 2013-04-09 02:32:16

+0

這應該不成問題。你應該能夠使用Clojure的[閱讀](http://clojuredocs.org/clojure_core/clojure.core/read)從文件中讀取表單,並將它傳遞給上面的宏。你嘗試過嗎? – leonardoborges 2013-04-09 02:44:23