Исключение нулевого указателя с использованием привязок в макросе Clojure - PullRequest
1 голос
/ 17 ноября 2011

Я получаю исключение нулевого указателя при выполнении макроса для некоторого взаимодействия Java, и я не могу понять, почему.

Я устанавливаю поля Java-объекта, используя карту с вложенными данными, и, поскольку имена ключей карты совпадают с именами полей объекта, я создал макрос:

(defmacro set-keys! [pose m k klst]
  `(set! (. ~pose ~(symbol (name k)))
         (double-array (map #(% (~(keyword (name k)) ~m)) ~klst))))

Для тестирования я определил pse как инициализированный объект Java с интересующими полями, установленными на ноль, и определил mp как упрощенную карту, которая все еще будет работать:

(def mp {:pos {:x 1 :y 2})

Теперь приходит странное поведение. Выполнение set-keys! с явно типизированными аргументами работает:

user> (set-keys! pse mp :pos [:x :y])
#<double[] [D@691ba57a>

Но если я использую, запустите код внутри let вызова:

user> (let [x :pos y [:x :y]]
        (set-keys! pse mp x y))

Я получаю исключение нулевого указателя с сообщением "Нет сообщения". как сообщение В чем здесь проблема?

EDIT: я определил pse с помощью (def pse (pose_t.)), pose_t - сгенерированный класс, а конструктор pose_t() инициализирует все массивы в его полях, но не инициализирует значения. Соответствующие строки кода класса для упрощенного примера:

public double pos[];

public pose_t() {
    pos = new double[3];
}

1 Ответ

3 голосов
/ 17 ноября 2011

Макро аргументы не оцениваются, поэтому ~(keyword (name k)) расширяется до - примерно - (keyword (name (quote x))) - что означает: x, а не: pos

По крайней мере, я думаю, что это проблема.Если нет, было бы неплохо, если бы вы могли включить определение для pse.

Добавление: вы можете проверить, к чему фактически расширяется макрос, оценив:

user> (macroexpand-1 '(set-keys! pse mp x y))
(set! (. pse x) (clojure.core/double-array (clojure.core/map
    (fn* [p1__2066__2067__auto__] (p1__2066__2067__auto__ (:x mp))) y)))

Обратите внимание на: x

Приложение 2: (. obj field) на самом деле также не оценивает field, что означает, что вам придется использовать отражение Java, чтобы сделать аргумент поля динамическим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...