doto returns the original object, not the results of any of the
following method calls. That means it works well for mutable objects,
where in the end you want the mutated object. But since Strings are
immutable, methods like toUpperCase are returning a new String, not
mutating the old one. So all you're getting back is your original
String.
Perhaps -> would work better in this case:
user=> (-> "hello" .toUpperCase (.replace "H" "J"))
"JELLO"
.. would also work, but I pretty much always prefer -> because you can
mix in non-methods, and the methods are clearly indicated with a
leading dot. In fact, I could imagine lobbying to have .. removed
(while we're making breaking changes...)
--Chouser
> But if I do this in a doto, it doesn't seem to work but
> I don't get any error message.
>
> user=> (doto (new java.lang.String "hello") (toUpperCase))
> "hello"
> user=> (class (new java.lang.String))
> #=java.lang.String
>
> Shouldn't this be working? If this is (by design) because strings are
> immutable (so no doto) shouldn't there be an error message?
>
> What am I missing here.
"doto" operates on an object and returns the object that it operated
on. In your case, it's the original string that gets returned. Strings
are immutable so the toUpperCase call created a new string which was
then thrown away.
The "->" operator will accomplish what you're looking for here. It
returns the result of the operations, each result becoming the input
for the next::
user=> (-> (String. "hello") .toUpperCase)
"HELLO"
--Steve
Another semantic marker here is 'do'. do in Clojure implies side-
effects. Since you can't uppercase a string by side effect, doto isn't
the right tool for this job.