2010-09-20 2 views
1

Этот вопрос тесно связан с this one, но я думаю, это более общий.Как мы можем создать «экземпляры» типа или записи «на лету»

Недавно я попытался создать «экземпляры» типа «на лету» с помощью мультиметодов (или с помощью уникального конструктора функций, если это возможно), основанный на теге метаданных. Я связал тип (класс java под капотом) с этим тегом, а затем я не знал, как продолжать элегантным способом (без отражения или строк в eval или java); new - особая форма, и с ней трудно справиться, хотя вы используете макросы.

В seudo-коде будет:

(def my-tagged-data (with-meta my-data {:my-type-tag my-ns.My-Type})) 
(def factory-function [tagged-data] 
    (create (:my-type-tag (meta tagged-data)) tagged-data)) 
+0

Повторное чтение комментария цитированного предыдущего вопроса, возможно, единственный способ изменить функции datatypes clojure: -/ – jneira

+0

Вы хотите написать собственный заводский код для каждого типа записи и связать его с типом записи так или иначе, чтобы вы может вызвать фабрику, используя имя типа записи (а не имя фабрики)? – Chouser

+0

mmm точно это была оригинальная идея, без явной фабрики, если это возможно, используя методы с несколькими методами или протоколы (или несколько с отправкой), чтобы добавить конструкторы расширяемым способом. – jneira

ответ

2

Вы можете предоставить заводские функции для ваших типов.

(def my-tagged-data (with-meta my-data {:my-type-factory `my-type-factory})) 

(defn factory-function 
    [tagged-data] 
    (@(resolve (:my-type-factory (meta tagged-data))) tagged-data)) 

Это может быть или не быть осуществимым.

+0

- это @ перед разрешением опечатки или взлома, неизвестных мне ?? я не обратил внимания на решимость, спасибо за это. – jneira

+0

@ отменяет действие var, возвращаемое решением, но необязательно в этом случае, потому что вы можете напрямую вызвать var. – cgrand

+0

Идея kotarak хороша, но instaed из символа, который вы можете прямо поставить на завод в метаданные и использовать глобальный реестр в качестве резервного для устаревших классов. – cgrand

0

Я думаю, что вы должны использовать отражение. (Лучше идея, чем eval, я думаю).

+0

. Кроме того, я пропустил что-то очевидное, потому что я не понимаю, как использовать newInstance , причина Integer/class не работает ни (Integer/newInstance) – jneira

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