Какой хороший метод toString для объекта deftype'd в clojure - PullRequest
5 голосов
/ 11 сентября 2010
(deftype Bag [state]
   Object
     (toString [bag]
       (str "Bag???" state)))

Я хочу, чтобы toString выглядел примерно так:

clojure.core=> (def b (Bag. {:apples 1 :bannanas 4}))
#'clojure.core/b
clojure.core=> (str b)
"BAG: {:apples 1 :bannanas 4}"

Каков хороший способ представления этой клочью?

"Bag/{:k :v}" 

лучше?Как сообщество вы называете ваши toStrings?

Ответы [ 2 ]

7 голосов
/ 11 сентября 2010

В зависимости от того, что именно вы пытаетесь сделать, самый простой способ - использовать defrecord:

user=> (defrecord Bag [state])
user.Bag
user=> (def b (Bag. :foo))
#'user/b
user=> b
#:user.Bag{:state :foo}

Хотя то, что вы видите выше, взято из pr, а не str:

user=> (str b)
"user.Bag@53e935f4"
user=> (prn b)
#:user.Bag{:state :foo}
nil

Итак, мы просто вносим изменения:

user=> (defrecord Bag [state]
         Object
         (toString [bag] (pr-str bag)))
user.Bag
user=> (def b (Bag. :foo))
#'user/b
user=> (str b)
"#:user.Bag{:state :foo}"
user=> (.toString b)
"#:user.Bag{:state :foo}"

Теперь, если вышеприведенное не подходит, тогда следующим вариантом будет добавление нового метода в print-method multi-метод. Google вокруг для деталей об этом.

В сторону: использование defrecord обычно предпочтительнее, чем deftype, если вы не делаете что-то очень низкого уровня.

5 голосов
/ 12 сентября 2010

Следующее для deftype.

user=> (deftype Bag [state] 
         Object 
         (toString [_] 
           (str "BAG: " (pr-str state))))
user.Bag
user=> (def b (Bag. {:apples 1 :bannanas 4}))
#'user/b
user=> (str b)
"BAG: {:bannanas 4, :apples 1}"
...