|
19 | 19 |
|
20 | 20 | ;; [clojure-plus](https://github.com/tonsky/clojure-plus) provides print-methods to improve printing many things. |
21 | 21 |
|
22 | | -(require 'clojure+.print) |
23 | | -^:kind/hidden |
24 | | -(clojure+.print/install-printers!) |
25 | | - |
26 | | -;; Once activated, we can print functions, atoms, namespaces, and more sensibly |
27 | | - |
28 | | -inc |
29 | | -(atom {}) |
30 | | -*ns* |
| 22 | +(comment |
| 23 | + (require 'clojure+.print) |
| 24 | + (clojure+.print/install-printers!)) |
31 | 25 |
|
| 26 | +;; Once activated, we can print functions, atoms, namespaces, and more sensibly. |
32 | 27 | ;; Clojure Plus adds printers for many types, |
33 | 28 | ;; but no printer is provided for Object, |
34 | 29 | ;; which remains as Clojure's default printing method. |
35 | 30 | ;; There are plenty of objects left over that print messily. |
36 | | -;; Going back to our channel example, it still prints the same: |
37 | | - |
38 | | -(async/chan) |
39 | 31 |
|
40 | 32 | ;; It's not hard to provide an Object print-method: |
41 | 33 |
|
42 | 34 | (defmethod print-method Object [x ^java.io.Writer w] |
43 | | - (.write w "#object ") |
44 | | - (.write w (.getName (class x)))) |
| 35 | + (.write w "#object [") |
| 36 | + (.write w (.getName (class x))) |
| 37 | + (.write w "]")) |
45 | 38 |
|
46 | 39 | (async/chan) |
47 | 40 |
|
|
93 | 86 |
|
94 | 87 | ;; Looking better, I can actually see the (strange) name of the functions. |
95 | 88 |
|
96 | | -;; Notice now that the string is not a valid symbol? |
97 | | -;; That's a problem if we follow the style of `clojure-plus` because it prints as tagged literals. |
98 | | -;; |
99 | | -;; `#object clojure.plus.print.objects.objects-and-protocols/%%/%%%` is not a valid Clojure expression. |
100 | | -;; In a sense it doesn't matter much if we are just printing, but it tends to confuse tools (and people). |
101 | | -;; So I recommend replacing all slashes after the namespace delimiter with `$` instead. |
102 | | -;; While we are at it... the namespace isn't helping us at all here. |
103 | | -;; Let's just show the name without the namespace. |
104 | | - |
105 | | -(defn format-class-name [s] |
| 89 | +(defn format-class-name ^String [s] |
106 | 90 | (let [[ns-str & names] (-> (remove-extraneous s) |
107 | 91 | (str/split #"/"))] |
108 | 92 | (if (and ns-str names) |
109 | | - (str/join "$" names) |
110 | | - s))) |
| 93 | + (str (str/join "$" names)) |
| 94 | + (-> s (str/split #"\.") (last))))) |
111 | 95 |
|
112 | 96 | (-> (((fn aaa [] (fn bbb [] (fn ccc []))))) |
113 | 97 | (class-name) |
114 | 98 | (format-class-name)) |
115 | 99 |
|
116 | | -;; That's really all we need. |
117 | | -;; Notice there is no `/` slash if we don't show the namespace, but we still can't use `/` because functions can nest arbitrarily. |
118 | | - |
119 | | -;; Side note about including or omitting the namespace. |
120 | | -;; There are many ways to get whatever representation you want, |
121 | | -;; so changing the printing behavior doesn't prevent anything. |
122 | | -;; The question is just would you like to see it or not? |
123 | | -;; I would argue that it's almost never useful, just a distraction. |
124 | | -;; On the other hand, the current behavior for printing vars is fully qualified. |
125 | | -;; Whatever your preference on showing the namespace, it should probably be consistent across printers. |
126 | | - |
127 | | -;; I'll assume you prefer including the namespace |
128 | | - |
129 | | -(defn format-class-name [s] |
130 | | - (let [[ns-str & names] (-> (remove-extraneous s) |
131 | | - (str/split #"/"))] |
132 | | - (if (and ns-str names) |
133 | | - (str ns-str "/" (str/join "$" names)) |
134 | | - s))) |
135 | | - |
136 | 100 | ;; Let's hook this up to the print-method for Object: |
137 | 101 |
|
138 | 102 | (defmethod print-method Object [x ^java.io.Writer w] |
139 | | - (.write w "#object ") |
140 | | - (.write w (-> (class-name x) (format-class-name)))) |
141 | | - |
142 | | -;; Notably this doesn't change function etc... because they are still using the `clojure-plus` print-method: |
| 103 | + (.write w "#object [") |
| 104 | + (.write w (-> (class-name x) (format-class-name))) |
| 105 | + (.write w "]")) |
143 | 106 |
|
| 107 | +*ns* |
144 | 108 | (((fn aaa [] (fn bbb [] (fn ccc []))))) |
145 | | - |
146 | | -;; In my opinion, the fn and multi print-methods of `clojure-plus` should be changed to the cleaner output. |
147 | | - |
148 | | -;; But it matters for our reify example: |
149 | | - |
150 | 109 | (stats/create-flow) |
151 | 110 |
|
152 | 111 | ;; What is this? It's a reified object that implements protocols. |
@@ -228,36 +187,17 @@ inc |
228 | 187 | ;; But we can improve the print-method to show protocols, |
229 | 188 | ;; bearing in mind it is a performance concern. |
230 | 189 |
|
231 | | -(defmethod print-method Object [x ^java.io.Writer w] |
232 | | - (let [class-name (.getName (class x)) |
233 | | - r (str/includes? class-name "$reify") |
234 | | - p (when r (first (protocol-ns-match-names x)))] |
235 | | - (.write w (if p |
236 | | - "#reify " |
237 | | - "#object ")) |
238 | | - (.write w (if p |
239 | | - (str p) |
240 | | - class-name)))) |
241 | | - |
242 | | -(stats/create-flow) |
243 | | - |
244 | 190 | ;; Showing the reified protocol isn't a big improvement, and probably not worth the performance. |
245 | 191 | ;; Probably not worth including in `clojure-plus`. |
246 | 192 |
|
247 | 193 | ;; Even if we don't care to improve reify (due to performance), |
248 | 194 | ;; I think the Object printer should still be improved to align with the other printers. |
249 | | -;; Let's go back to the basic Object print-method without protocol detection. |
250 | | - |
251 | | -(defmethod print-method Object [x ^java.io.Writer w] |
252 | | - (.write w "#object ") |
253 | | - (.write w (-> (class-name x) (format-class-name)))) |
254 | 195 |
|
255 | | -;; O.K. |
256 | 196 | ;; Are we giving up anything? |
257 | 197 | ;; Remember we removed the unique identifiers like `/evalNNNNN/`. |
258 | 198 | ;; When would those be useful? |
259 | 199 | ;; Hold onto your hats! |
260 | | -;; We are about to try to find an Object by it's class-name: |
| 200 | +;; We are about to try to find an Object by a class-name: |
261 | 201 |
|
262 | 202 | (defn find-class [class-name] |
263 | 203 | (try |
|
0 commit comments