toUpperCase on java.lang.String

350 views
Skip to first unread message

Parth Malwankar

unread,
Oct 15, 2008, 11:20:48 PM10/15/08
to Clojure
Calling a java method on a string directly works.

user=> (.toUpperCase "hello")
"HELLO"
user=> (class "hello")
#=java.lang.String

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.

Parth

Chouser

unread,
Oct 15, 2008, 11:44:07 PM10/15/08
to clo...@googlegroups.com
On Wed, Oct 15, 2008 at 11:20 PM, Parth Malwankar
<parth.m...@gmail.com> wrote:
>
> 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

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

Stephen C. Gilardi

unread,
Oct 15, 2008, 11:47:04 PM10/15/08
to clo...@googlegroups.com
Hi Parth,

> 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

Timothy Pratley

unread,
Oct 16, 2008, 2:17:15 AM10/16/08
to Clojure
Oh wow, powerful syntax!

> 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...)

What does 'mix in non-methods' means? I read the (doc ->) but I really
don't follow that explination.
I agree that (-> is a much nicer syntax than (.. and now that I see
how you use it will use it instead.

Speaking of which... I have to say that for someone getting their head
around form expressions the docs are quite terse. Its not always
trivial to find a simple example (I usually find something searching
the groups and wiki and non-api sections of the website). IMHO The
docs would really benefit from an example for each entry. Now I know
that is a great deal of work, so I've started a wiki entry:
http://en.wikibooks.org/wiki/Clojure_Programming_Examples
Where I'm attempting to gather examples I come across from various
sources which have helped me. The idea being that if it ever gets
close to covering the api, they could be somehow programatically
stripped into the (doc and voila there would be examples for every
syntax definition. Just meantioning so that others can look/add and or
comment on the idea.


Regards,
Tim.

mb

unread,
Oct 16, 2008, 3:09:00 AM10/16/08
to Clojure
Hi,

On 16 Okt., 08:17, Timothy Pratley <timothyprat...@gmail.com> wrote:
> What does 'mix in non-methods' means? I read the (doc ->) but I really
> don't follow that explination.

-> is more general than .. . .. only works on objects.

(.. foo (bar baz) (frob nicate))

is equivalent to

(. (. foo bar baz) frob nicate)

However -> works on everything, but with the same idea.

user=> (-> true (if inc dec) (map [1 2 3]))
(2 3 4)

or expanded

(map (if true inc dec) [1 2 3])

So one can also use macros and normal functions in ->,
ie. non-methods.

Sincerely
Meikel

Timothy Pratley

unread,
Oct 16, 2008, 4:48:15 AM10/16/08
to Clojure
Thanks!

Rich Hickey

unread,
Oct 16, 2008, 7:29:51 AM10/16/08
to Clojure
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.

doto can't throw an error here or elsewhere when used on an immutable
object because:

a) It can't generally know which objects are immutable
b) Even immutable objects may have methods with other side-effects

Rich

Stephen C. Gilardi

unread,
Oct 16, 2008, 9:01:49 AM10/16/08
to clo...@googlegroups.com

On Oct 16, 2008, at 7:29 AM, Rich Hickey wrote:

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.

Neat.

I explored the "do..." marker a little with Clojure:

- user=> (filter #(re-matches #"do.*" %) (map #(-> % first name) (ns-publics 'clojure)))
  ("dorun" "doseq" "dosync" "dotimes" "doubles" "doto" "double-array" "doall" "double" "doc")

 The "do implies a side-effect emphasis" pattern holds for dorun, doseq, dosync, dotimes, doto, and doall.

- The doc for the function "repeatedly" mentions "presumably with side effects", but it doesn't begin with "do".

- The special form "do" is just about grouping, independent of side effects.

I recently changed the clojure.contrib.sql/with-results macro to remove a "doseq" call. Now it just provides the sequence of results and lets the caller decide what to do with it which is a lot more flexible.

Coming from an imperative programming mindset, I find that imperative/side-effecting is often the first thing that occurs to me. When I work on the code to make it more functional, it's pretty much uniformly an improvement in how flexible and composable it is.

As a very welcome bonus, I'm also finding it's a lot more fun!

--Steve

Parth Malwankar

unread,
Oct 16, 2008, 10:04:40 AM10/16/08
to Clojure
That makes sense. Thanks everyone for all the help.

Parth
Reply all
Reply to author
Forward
0 new messages