What's a good toString method for a deftype'd object in clojure
Asked Answered
O

2

6
(deftype Bag [state]
   Object
     (toString [bag]
       (str "Bag???" state)))

I want the toString to look something like

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

What is a nice clojurey way of representing that information? Is

"Bag/{:k :v}" 

better? How does the community do you call your toStrings?

Overcapitalize answered 10/9, 2010 at 22:41 Comment(0)
L
5

The following is for 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}"
Londrina answered 11/9, 2010 at 20:2 Comment(0)
L
8

Depending on exactly what you're trying to do, the simplest way is to use defrecord:

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

Though what you see above is from pr, not str:

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

So we just make a change:

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}"

Now, if the above is not suitable, then next option would be to add a new method to the print-method multi-method. Google around for details on that.

Aside: Using defrecord should generally be preferred over deftype unless you're doing something very low-level.

Londrina answered 11/9, 2010 at 1:2 Comment(3)
Define low level. I'm trying to create new collection types (bags and multimaps). When do you use defrecord or deftype and why?Overcapitalize
Using this method with deftype yields a java.lang.StackOverflowErrorOvercapitalize
Yes, if you're creating new collection type, deftype is probably correct, whereas defrecord is more appropriate when needing something like a struct of some domain data.Londrina
L
5

The following is for 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}"
Londrina answered 11/9, 2010 at 20:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.