2011-01-02 3 views
13

я создал запись так:Невозможно импортировать Clojure записи

(defrecord User [user-id email]) 

: но когда я пытаюсь получить доступ к нему из другого пространства имен-я получаю ошибку:

(User. "name" "email") 

Java .lang.IllegalArgumentException: Не удается разрешить имя класса: Пользователь

Это работает, когда я делаю:

(oe.model.modelcore.User. "name" "email") 

: Я знаю, что нужно будет импортировать класс Java, но есть ли способ для Clojure сделать это автоматически, когда я делаю:

(use 'oe.model.modelcore :reload) 

ответ

13

Технически вы должны потребовать его (необязательно использовать его), чтобы файл, содержащий определение записи, был скомпилирован и класс был создан. Затем вы должны импортировать его так, чтобы он был доступен для создания в качестве класса Java. Если вы создаете функцию-конструктор в первых ns, например

(defn new-user [id email] 
    (User. id email)) 

тогда вам не нужно будет импортировать его в вызывающий ns.

Я написал это до некоторое время назад здесь:

+3

К счастью, это не более необходимо, начиная с Clojure 1.3, где записи стали гражданами первого сорта. Просто хотел оставить комментарий для людей, читающих это сейчас. –

+0

Из моего опыта вам необходимо скомпилировать AOT и потребовать и импортировать записи. (Конечно, мы использовали библиотеку схем призмы для проверки наших записей) –

9

Вы должны импортировать запись так:

(ns some-ns 
    (:import [oe.model.modelcore User])) 
+0

Я изменил принятый ответ на этот вопрос, так как это был ответ, который работал на меня в январе 2014 – Zubair

8

В своем вопросе вы создаете запись, затем вызывая конструктор для класса, генерируемого в качестве побочного эффекта. Для этого вам нужно импортировать этот класс, как указано в другом ответе.

Однако, imho предпочтительный путь (так как Clojure 1.4) должен использовать функции конструктора, созданные defrecord (здесь они будут называться ->User и map->User). Эти функции позволяют избежать форм взаимодействия и просто ссылаться на функции конструктора, как и на любую другую функцию. Избегая Interop, это более портативным менее Hosty решение:

(ns some-ns 
    (:require [oe.model.modelcore :refer (->User)])) 

(def user (->User "name" "email")) 
7

Это может быть очень сложно, если у вас есть - (тир) в вашем пространстве имен.

As it turns out there were two errors:

– Importing defrecord from another namespace is not just :use. I had to first :require the namespace, then import the defrecord. This was a trivial problem to solve and I figured it out quickly. Only this did not work in my case

– Dashes “-” and Underscores “_” are a nuisance since we are mixing Lisp with Java. While the file system uses underscores Clojure converts things to dashes. Brilliant.

So to fix the second error I use the follow in the ns block

(ns adder.core 
    (:require building-blocks.activity) 
    (:import [building_blocks.activity Activity])) 

https://cyrax.wordpress.com/2013/07/22/clojure-importrequireuse-defrecord-from-another-namespace/

+1

+1 Проблема подчеркивания в: import - это то, что все еще кусало меня, поэтому спасибо за добавление этого после того, как OP принял ответ. –

+0

Извините за downvoting, это по ошибке, и я не могу забрать его обратно! – Aspasia

+0

Нажмите на голосование :) – MAGx2

Смежные вопросы