A chain of function vars

95 views
Skip to first unread message

Simon Katz

unread,
May 26, 2013, 5:33:24 PM5/26/13
to clo...@googlegroups.com
If I define a chain of vars like this...

(defn f1 [] 42)

(def f2 #'f1)

(def f3 #'f2)

...when I call f3 the chain of vars is followed:

(f3) ; => 42

Out of curiosity, where is this following-the-chain defined?

I looked at http://clojure.org/evaluation which simply says "The result of the evaluation of the operator is [...] cast to IFn (the interface representing Clojure functions), and invoke() is called on it".

--Simon

JvJ

unread,
May 26, 2013, 6:09:30 PM5/26/13
to clo...@googlegroups.com
I could be wrong, but I believe that symbols and vars are separate entities.  

f1 is a symbol which is associated with a var that contains the function.  When you evaluate the symbol 'f1, it looks at the association to find the var.

It looks like, when you define f2 and f3 to take on those variables, the symbols 'f2 and 'f3 get associated with the same var as 'f1.  So I don't think there's any chaining together.  They're just associated with a single var.

Again, I could be wrong, but I believe this is how it works.

JvJ

unread,
May 26, 2013, 6:18:57 PM5/26/13
to clo...@googlegroups.com
Actually, I spoke WAY too soon.

It looks like it has to do with the way that Var is cast to IFn.

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java

Check out lines 391 and 410.  When invoked, the result of fn() is invoked.  fn() casts deref() (the data contained by the var) into a function.

If the var contains another var, casting that var to an IFn will result in a recursive call.

For example:

f3 casts f2 to an IFn.
f2 casts f1 to an IFn.
f1 casts the function to an IFn (resulting in the function).

So the "chaining together" is defined in the invoke method and the casting process.


On Sunday, 26 May 2013 17:33:24 UTC-4, Simon Katz wrote:

JvJ

unread,
May 26, 2013, 6:26:18 PM5/26/13
to clo...@googlegroups.com
Additionally, we can make the chain into a loop.


(defn f1 [] 42)
(def f2 #'f1)
(def f3 #'f2)
(def f1 #'f3)

(f3) ==> stack overflow

Simon Katz

unread,
May 26, 2013, 6:35:55 PM5/26/13
to clo...@googlegroups.com
Cool; thanks. That's an implementation-level explanation, which is fine as far as it goes.

Can anyone point at a specification-level explanation?

JvJ

unread,
May 26, 2013, 8:04:42 PM5/26/13
to clo...@googlegroups.com
I suppose that would depend on the specifications for how various objects are cast to functions.  For instance, vectors, maps, sets, keywords, etc. have their own specific ways of acting as functions.  Do you know where that is specified?

Simon Katz

unread,
May 26, 2013, 8:16:44 PM5/26/13
to clo...@googlegroups.com
http://clojure.org/data_structures defines how the various data structures implement IFn.

I would expect either http://clojure.org/vars or http://clojure.org/Evaluation to talk about the chaining of vars, but if either does I'm missing it.
Reply all
Reply to author
Forward
0 new messages