> I don't understand doto.
Apparently. The doc says:
user> (doc doto)
-------------------------
clojure.core/doto
([x & forms])
Macro
Evaluates x then calls all of the methods and functions with the
value of x supplied at the from of the given arguments. The forms
are evaluated in order. Returns x.
(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
nil
Ok, that's not very clear. I suspect that "from" is a typo for
"front". However, doto is a macro, so macroexpand-1 can help:
> Suppose I try the following:
>
> user=> (doto 1 println)
> 1
> 1
> user=>
user> (macroexpand-1 '(doto 1 println))
(clojure.core/let [G__1967 1] (println G__1967) G__1967)
Reformatting:
(clojure.core/let [G__1967 1]
(println G__1967)
G__1967)
So it assigns the first argument to the generated variable G__1967,
then calls println on that variable, and finally returns it. Hence you
get two 1's printed.
> Now suppose I try the following:
> user=> (doto 1 #(println (inc %)))
> 1
> user=>
user> (macroexpand-1 '(doto 1 #(println (inc %))))
(clojure.core/let [G__1984 1] (fn* G__1984 [p1__1980] (println (inc p1__1980))) G__1984)
Reformatting:
(clojure.core/let [G__1984 1]
(fn* G__1984 [p1__1980] (println (inc p1__1980)))
G__1984)
fn* is an undocumented internal function returned by the #(...)
reader macro (not sure that's quite right for Clojure, but the effect
is the same). The doto macro rewrites that form to insert its first
argument at the front of the given arguments, in front of the argument
vector. fn* returns an function, without invoking it. That's
discarded, and the value of the first argument to the macro is
returned, as documented.
> But if I make the following definition:
> (defn some-function [x]
> (println (inc x)))
>
> user=> (doto 1 some-function)
> 2
> 1
> user=>
user> (macroexpand-1 '(doto 1 some-function))
(clojure.core/let [G__2012 1] (some-function G__2012) G__2012)
This mimics the first form - the symbol that is the "forms" argument
is wrapped in a list and the first argument inserted as it's first
argument.
> Why did #(println (inc %)) not work and some-function work?
Because you didn't invoke the function returned by #(println (inc
%). Doto treats the (fn* ...) the way it treats all lists, not the way
it treats symbols, which is wrong in this case. If you invoke that
function without arguments, then the doto macro will correctly insert
it's first argument into the call:
user> (doto 1 (#(println (inc %))))
2
1
user> (macroexpand-1 '(doto 1 (#(println (inc %)))))
(clojure.core/let [G__2046 1] ((fn* [p1__2042] (println (inc p1__2042))) G__2046) G__2046)
Reformatting again:
(clojure.core/let [G__2046 1]
((fn* [p1__2042] (println (inc p1__2042))) G__2046)
G__2046)
It's a little clearer if you use (fn instead of #(, since that leaves
your function intact, but has the same problem:
user> (doto 1 (fn [x] (println(inc x))))
1
user> (macroexpand-1 '(doto 1 (fn [x] (println(inc x)))))
(clojure.core/let [G__2103 1] (fn G__2103 [x] (println (inc x))) G__2103)
or:
(clojure.core/let [G__2103 1]
(fn G__2103 [x] (println (inc x)))
G__2103)
vs:
user> (doto 1 ((fn [x] (println(inc x)))))
2
1
user> (macroexpand-1 '(doto 1 ((fn [x] (println(inc x))))))
(clojure.core/let [G__2123 1] ((fn [x] (println (inc x))) G__2123) G__2123)
or
(clojure.core/let [G__2123 1]
((fn [x] (println (inc x))) G__2123)
G__2123)
<mike
--
Mike Meyer <m...@mired.org> http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.
O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
Based on the docs, I was confused by that because I expected a hash
map (with keys a and b). When I ran it locally, I got:
#<HashMap {b=2, a=1}>
which was what I expected.
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood