lexical fn names and defn vs. memoize in light of 1.3 changes to vars

43 views
Skip to first unread message

Kevin Downey

unread,
Jun 6, 2011, 4:29:31 PM6/6/11
to Clojure Dev
currently (defn foo [x] (foo x)) expands to something like (def foo
(fn foo [x] (foo x))) so the fn is bound to foo lexically in the scope
of the fn body.

because of this lexical shadowing self calls to fns defined with defn
do not incur the overhead of var dereferencing, I assume this is the
reason it was added.

the lexical shadowing also breaks memoization if you create the
memoized functions via (alter-var-root #'foo memoize) and several
macros here and there emit code in this style, since reusing defn is
the easiest way to get all the good juicy metadata bits like arglists,
etc.

1.3 has changes to eliminate some of the cost of going through the var.

has the cost been lowered enough to remove the lexical shadowing in
the expansion of defn?

--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

Rich Hickey

unread,
Jun 6, 2011, 8:06:50 PM6/6/11
to cloju...@googlegroups.com

On Jun 6, 2011, at 4:29 PM, Kevin Downey wrote:

> currently (defn foo [x] (foo x)) expands to something like (def foo
> (fn foo [x] (foo x))) so the fn is bound to foo lexically in the scope
> of the fn body.
>
> because of this lexical shadowing self calls to fns defined with defn
> do not incur the overhead of var dereferencing, I assume this is the
> reason it was added.
>
> the lexical shadowing also breaks memoization if you create the
> memoized functions via (alter-var-root #'foo memoize) and several
> macros here and there emit code in this style, since reusing defn is
> the easiest way to get all the good juicy metadata bits like arglists,
> etc.
>
> 1.3 has changes to eliminate some of the cost of going through the
> var.
>
> has the cost been lowered enough to remove the lexical shadowing in
> the expansion of defn?
>

Probably, although some comparative testing of that would be nice.

Rich

Kevin Downey

unread,
Jun 7, 2011, 3:57:43 PM6/7/11
to cloju...@googlegroups.com
tests indicate they are close performance-wise

https://gist.github.com/1013008

results in

$ java -jar clojure.jar ~/src/lexicaltest.clj
lexical binding run 0
"Elapsed time: 86.739 msecs"
lexical binding run 1
"Elapsed time: 8.062 msecs"
lexical binding run 2
"Elapsed time: 16.182 msecs"
var binding run 0
"Elapsed time: 61.136 msecs"
var binding run 1
"Elapsed time: 40.317 msecs"
var binding run 2
"Elapsed time: 11.641 msecs"
$

looks like going through the var takes a little more to inline?

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

David Nolen

unread,
Jun 8, 2011, 11:31:34 PM6/8/11
to cloju...@googlegroups.com
FWIW I'd let to get behind this fix as well if the performance is good. Lexical shadowing makes it hard (impossible?) for core.logic to support scoped tabling via binding.

David

David Nolen

unread,
Jun 8, 2011, 11:37:43 PM6/8/11
to cloju...@googlegroups.com
And I meant impossible with defn, it's certainly possible with def.

Stuart Halloway

unread,
Jun 9, 2011, 2:08:43 PM6/9/11
to cloju...@googlegroups.com
David, can you or Kevin convert this into a JIRA ticket?

Besides the information already collected, any observations or brainstorms on things that might be broken by this change would be very helpful.

Stu
Stuart Halloway
Clojure/core
http://clojure.com

Kevin Downey

unread,
Jun 11, 2011, 3:37:50 PM6/11/11
to cloju...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages