2012-04-16 2 views
3

Вероятно очевидно, но, учитывая этот код (от http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/reify):материализовать, ToString

(defn reify-str [] 
    (let [f "foo"] 
    (reify Object 
     (ToString [this] f)))) 

(defn -main [& args] 
    (println (reify-str)) 
    (System.Console/ReadLine)) 

Почему я получаю этот выход?

#<ui$reify_str$reify__4722__4727 foo> 

Вместо:

foo 

Я бегу ClojureCLR в Windows, если это помогает. Благодаря!

+0

Похож: http://stackoverflow.com/questions/5306015/equivilent-of-javas-tostring-for-clojure-функции – sw1nn

ответ

5

Основная проблема заключается в том, что Clojure REPL использует print-method, а не .toString. Вы должны определить print-method для вашего типа. Это немного раздражает типы reified, поскольку это делает их довольно подробными. Вы должны сделать что-то вроде этого:

(defn reify-str [] 
    (let [f "foo" 
     r (reify Object 
      (ToString [this] f))] 
    (defmethod clojure.core/print-method (type r) [this writer] 
     (print-simple f writer)) 
    r)) 

(. Я только проверил это в ванили Clojure, но я думаю, что это то же самое в ClojureCLR)

На данный момент, хотя, вы» почти лучше создавать фактический тип вместо повторного создания, потому что вы каждый раз пересматриваете метод. (Я думаю, вы могли бы сделать какое-то глобальное состояние, чтобы избежать необходимости, но ... ну, вы можете понять, почему определение типа может быть предпочтительным.)

+0

Это действительно работает, просто протестировало его. Кстати, так же как и фрагмент, который я наклеил выше, * if *, я завершаю его при вызове (str ...) (я думаю, что вызывает метод ToString, тогда как println вызывает метод print). –

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