2011-01-02 8 views
9

Javaオブジェクト内の多くの異なるフィールドを設定するコードをファクタ化するにはどうすればよいですか?私は期間がマクロで、文字通り(最初のフィールド)を評価しようとするためしかし、これは動作しませんファクタClojureコードでJavaオブジェクトの多くの異なるフィールドを設定する

(doseq [field '((name "Chris") (age 100) (salary 5000))] 
    (set! (. employee (first field)) (second field))) 

(set! (. employee name) "Chris") 
(set! (. employee age) 100) 
(set! (. employee salary) 5000) 

を考慮したいと思います。ちなみに、私はフィールドを設定することは良い方法ではないことを理解しています。私はレガシーコードと相互運用する必要があります。あなたは試してみてください

答えて

7

はセッターを使用してみてください - しかし、あなたは選択の余地がないと本当にする必要がある場合これを除外すると、このようなマクロができます:

(defmacro set-all [object & fields-and-values] 
    (let [obj-sym (gensym)] 
    `(let [~obj-sym ~object] 
     [email protected](for [[field value] (partition 2 fields-and-values)] 
      `(set! (. ~obj-sym ~field) 
        ~value))))) 

オブジェクトを生成する式に副作用がある場合は、gensymが必要です。

使用例:

user> (def p (java.awt.Point.)) 
#'user/p 
user> (set-all p x 4 y 5) 
5 
user> p 
#<Point java.awt.Point[x=4,y=5]> 
5

(defmacro set-all! [obj m] 
    `(do [email protected](map (fn [e] `(set! (. ~obj ~(key e)) ~(val e))) m) ~obj)) 

例:

(def a (java.awt.Point.)) 
(set-all! a {x 300 y 100}) 

macroexpandは、すべて:

(do (set! (. a x) 9) 
    (set! (. a y) 7) 
    a) 
+0

そのような方法は存在しません。 – chris

+0

ああ、あなたはフィールドを設定しています。注意を払っていないという私のせいです。私は自分の答えを更新しました。 – Psyllo

関連する問題