A few questions

2 views
Skip to first unread message

Krukow

unread,
Oct 9, 2008, 2:39:23 AM10/9/08
to Clojure
Hi, I am a Clojure beginner, but I am definitely staying for more! I
heard about Clojure when Guy Steele mentioned it (just as a subtle
remark) in a talk about Fortress at JAOO 2008. Thought that when he
mentions it, it will probably be worth taking a look ;-)

WOW. I've just seen the web presentations and read the website, and I
was just blow away. Very cool. Rich you are my new hero :-)


Anyway, I was running through the examples of the site with a REPL by
my side. And I noticed something wierd. It's the rebind example from
http://clojure.org/concurrent_programming. Here is the output.

krukow:~/languages/clojure/trunk$ cl
Clojure
user=> (defn loves [x y]
(str x " loves " y))
#'user/loves
user=> (defn test-rebind []
(println (loves "ricky" "lucy"))
(let [str-orig str]
(binding [str (fn [& args]
(println "Logging str")
(apply str-orig args))]
(println (loves "fred" "ethel")))))
#'user/test-rebind
user=> (test-rebind)
ricky loves lucy
Logging str
Logging str
Logging str
Logging str
Logging str
fred loves ethel
nil
user=>


Now the question is why is it logging 5 times? Is this a bug, or has
something fundamental changed? I checked out Clojure from SVN a few
days ago.
krukow:~/languages/clojure/trunk$ svn info

Path: .
URL: https://clojure.svn.sourceforge.net/svnroot/clojure/trunk
Repository Root: https://clojure.svn.sourceforge.net/svnroot/clojure
Repository UUID: b4165764-bd0f-0410-b771-ab16a44d2305
Revision: 1051
Node Kind: directory
Schedule: normal
Last Changed Author: rhickey
Last Changed Rev: 1051
Last Changed Date: 2008-10-05 17:02:27 +0200 (Søn, 05 Okt 2008)


Cheers,
- Karl

mb

unread,
Oct 9, 2008, 8:35:10 AM10/9/08
to Clojure
Hi,

On 9 Okt., 08:39, Krukow <karl.kru...@gmail.com> wrote:
> (str x " loves " y))
>
> Now the question is why is it logging 5 times? Is this a bug, or has
> something fundamental changed? I checked out Clojure from SVN a few
> days ago.

Have a look at the implementation of str in boot.clj:
...
([x & ys]
(loop [sb (new StringBuilder #^String (str x)) more ys]
(if more
(recur (. sb (append (str (first more)))) (rest more))
(str sb))))
...

First logging to get there.
Second logging in the second line: (str x)
Third logging in 4th line: (str (first more)) ; (first more) == "
loves "
Fourth logging in 4th line: (str (first more)) ; (first more) == y
Fifth logging in 5th line: (str sb)

Sincerely
Meikel

Rich Hickey

unread,
Oct 9, 2008, 9:48:46 AM10/9/08
to Clojure
Which still leaves the question - what has changed?

The answer is, self-calls such as that in str used to be compiled into
direct invocations of the same function object, rather than going
through the var. Currently they go through the var. I've yet to
profile the performance difference, but the liability of direct self
call is that a long running function that called itself couldn't be
updated/fixed, since it would never re-read the new code. That said,
in practice such long-running self callers usually end up being agents
whose recursive action sends take the form of #'vars, ensuring the use
of new definitions.

The way it currently works makes the long-running case thought-free,
but if there ends up being a big perf difference I may switch it back
and document the techniques to use for the long-running case, since it
is certainly the minority.

In any case, the example output on the site is currently mismatched
with the behavior and I'll have to come up with a better one.

Rich
Reply all
Reply to author
Forward
0 new messages