Код фактора Clojure, устанавливающий множество различных полей в объекте Java - PullRequest
9 голосов
/ 02 января 2011

Как мне учесть код, устанавливающий много разных полей в Java-объекте? Я бы хотел, чтобы фактор

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

до

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

Однако это не сработает, потому что точка является макросом и пытается оценить (первое поле) буквально. Кстати, я понимаю, что установка полей не является хорошей практикой. Мне нужно взаимодействовать с устаревшим кодом.

Ответы [ 2 ]

8 голосов
/ 02 января 2011

Попробуйте использовать сеттеры - но если у вас нет выбора и вам действительно нужно это разложить, такой макрос подойдет:

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

Генсим необходим в том случае, если выражение, дающее объект, имеет какие-либо побочные эффекты.

Пример использования:

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]>
6 голосов
/ 02 января 2011

Вы можете попробовать:

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

Пример:

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

Macroexpand-all:

(do (set! (. a x) 9)
    (set! (. a y) 7)
    a)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...