On Tue, Dec 30, 2008 at 4:56 PM, wubbie <sunj...@gmail.com> wrote:
>
> Why do we need to specify the second argument(#'func) is a function,
> not a variable?
> the syntax of  send-off required  a function as the second arg?

The second argument will be called as a function -- if it's not
callable (doesn't implement IFn), you'll get an exception:

user=> (send-off (agent nil) 42)
java.lang.ClassCastException: java.lang.Integer cannot be cast to
clojure.lang.IFn

Perhaps you're asking why #'func is sometimes used instead of just
func?  This is probably because the code was written to work with
older versions of Clojure.  The difference is a bit subtle, but the
overview is that the #' prefix used to be required if you wanted to be
able to update the definition of 'func' and have the next send it made
to itself use that new definition.  This is no longer necessary, and
you can now use simply: (send-off *agent* func)

I don't understand all the details of what changed (or when), but
here's what I do know.  #'func evaluates to the Var named "func"
(which in turn holds the current value, presumably a function).  On
the other hand just plain 'func' evaluates to the *current value* of
the Var named func.  To demonstrate the difference:

user=> filter ; get the current value of filter
#<core$filter__3592 clojure.core$filter__3...@c3e9e9>
user=> (var filter) ; get the Var named "filter" -- can be written #'filter
#'clojure.core/filter
user=> (deref (var filter)) ; get the Var, and then the value -- can
be written @#'filter
#<core$filter__3592 clojure.core$filter__3...@c3e9e9>

Note the return value of the first and last examples are the same,
because they're doing essentially the same thing.

But I said 'send-off' needs a function, so how can we use #'func which
actually passes in a Var?  That's because Vars implement IFn -- when
called, they deref themselves and call their current value:

user=> (instance? clojure.lang.IFn #'filter)
true
user=> (#'filter identity [1 nil 2])
(1 2)

Presumably in some older version of Clojure, using the plain symbol
'func' caused the Var to be deref'ed only once, such that the initial
value of the Var was used even when if you used 'def' or 'defn' to
update the implementation for 'func'.

I don't know when this initial deref happened -- I don't think it
could have been at compile time, or there would have been no way to
forward-declare and have mutually-dependant functions definitions.
Perhaps it was the first time 'func' was called?  Anyway, it's easy to
demonstrate that the #'func format is no longer needed for
self-sending agents:

user=> (defn act [i] (Thread/sleep 1000) (prn i) (send-off *agent* act) (inc i))
#'user/act
user=> (send-off (agent 100) act)
#<Agent clojure.lang.ag...@1a61172>
user=> 100
101
102
103
(defn act [i])
#'user/act
user=> 104

After the manual 'send-off', a number was printed every second.  Then
I used 'defn' to update the Var named 'act' to be a function that does
nothing all. Because 'act' was sitting in it's 'sleep' call, one more
number was printed, but the next 'send-off' used the new definition of
'act' and nothing more was done.

--Chouser

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to