a question about binding

2 views
Skip to first unread message

Eric

unread,
Feb 1, 2009, 12:04:15 PM2/1/09
to Clojure
I recently wrote on my blog that using #' was a good way to make sure
that you get the function definition you want despite the symbol being
rebound within a let. For instance:

(let [list 10]
(#'list 1 2 3))

=> (1 2 3)

cgrand responded (here: http://www.reddit.com/r/programming/comments/7tny8/the_beauty_of_lisp1/c07dce4)
that this is not the preferred way, since it can be rebound using
binding. Hence:

(let [list 10]
(binding [list +]
(#'list 1 2 3)))

=> 6

He said that I should use clojure.core/list instead of #'list. That
is, to reference it with a fully-qualified name. But my understanding
is that binding still changes clojure.core/list withing the binding
form. Here, from my REPL:

(let [list 10]
(binding [list +]
(clojure.core/list 1 2 3)))

=> 6

So, my question is this: what is the difference/relationship between
#' and the fully-qualified name?

When should they be used? What are the standard idioms for using
these?

Stephen C. Gilardi

unread,
Feb 1, 2009, 2:18:23 PM2/1/09
to clo...@googlegroups.com

On Feb 1, 2009, at 12:04 PM, Eric wrote:

> So, my question is this: what is the difference/relationship between
> #' and the fully-qualified name?

#'x is a sequence of characters that the reader (LispReader.java)
translates into (var x) when reading. (see http://clojure.org/special_forms#var)
.

The simplest way to see this is by quoting it at the repl:

user=> (quote #'x)
(var x)

The purpose of the "var" special form is to return the var object
named by its argument (a symbol). It does this by using the symbol's
name part as a key in the ns-map for a namespace: (see clojure.core/ns-
map)

- If the symbol has a namespace part, var uses the namespace it names;
- If not, var uses the current namespace (*ns*).

If a symbol has a namespace part, using #' or var is unnecessary
because because such a symbol cannot refer to a function argument or
let-bound local.

For symbols without a namespace part, by using (var x) or #'x, you're
specifying you want the var object associated with that symbol in the
ns-map of the current namespace rather than leaving open the
possibility of getting the value of a function argument or let-bound
local named by that symbol.

> When should they be used? What are the standard idioms for using
> these?


Here are some suggestions of mine. I don't claim they're standard:

- Avoid using an argument name or let-bound local name that "shadows"
the (unqualified) name of a var you need to use within its scope
- Failing that, use a namespace qualified symbol to refer to the var
- If namespace qualifying a symbol is too verbose, use "alias" to
create a shorter name for the namespace
- If that's still too verbose, use #' or (var ...) to refer to the
var in the current namespace
- #'x and (var x) are equivalent. Use whichever you find readable and
adequately succinct.

Regarding binding itself, binding a var is an operation on the var
object itself. For a given var, that operation is the same and has the
same effect no matter how you acquired a reference to the var:

- using a fully qualified symbol name
- by resolution of a simple symbol name that's not shadowed by a
function argument or let-bound local
- by resolution of a simple symbol name within a var special form (or
#')
- by direct lookup in the ns-map for a namespace

Your experiment proved that.

--Steve

Eric

unread,
Feb 1, 2009, 5:01:28 PM2/1/09
to Clojure
Thanks so much!

Christophe Grand

unread,
Feb 2, 2009, 3:13:57 AM2/2/09
to clo...@googlegroups.com
Eric a écrit :

> He said that I should use clojure.core/list instead of #'list. That
> is, to reference it with a fully-qualified name. But my understanding
> is that binding still changes clojure.core/list withing the binding
> form. Here, from my REPL:
>
> (let [list 10]
> (binding [list +]
> (clojure.core/list 1 2 3)))
>
> => 6
>
> So, my question is this: what is the difference/relationship between
> #' and the fully-qualified name?
>

There's not so much difference when they are used in function position
but in argument position they behave differently.
Below is an example (from
http://clj-me.blogspot.com/2009/01/shadowing-global-names.html) where
you can see that with a name (I could have used a qualified name) you
pass the current value of the binding while with #' you pass the var
itself and those values will behave differently if they are "leaked"
outside of the calling scope (eg: sent to another thread or agent, used
in a lazy sequence or a delay, stored in a mutable box etc.)

(def a (map str (range 10)))
(def b (map #'str (range 10)))
(take 5 a)
/("0" "1" "2" "3" "4")/
(take 5 b)
/("0" "1" "2" "3" "4")/
(binding [str identity] (doall a))
/("0" "1" "2" "3" "4" "5" "6" "7" "8" "9")/
(binding [str identity] (doall b))
/("0" "1" "2" "3" "4" *5 6 7 8 9*)/

Christophe

Christophe Grand

unread,
Feb 2, 2009, 3:28:06 AM2/2/09
to clo...@googlegroups.com
Stephen C. Gilardi a écrit :

> Here are some suggestions of mine. I don't claim they're standard:
>
> - Avoid using an argument name or let-bound local name that
> "shadows" the (unqualified) name of a var you need to use within its
> scope
> - Failing that, use a namespace qualified symbol to refer to the var
> - If namespace qualifying a symbol is too verbose, use "alias" to
> create a shorter name for the namespace
I agree on these three first steps.

> Regarding binding itself, binding a var is an operation on the var
> object itself. For a given var, that operation is the same and has the
> same effect no matter how you acquired a reference to the var:

Except that in one case (name) you acquire the current value of the var
but not the var itself. It doesn't matter as long as you are in function
position but, elsewhere, it makes a difference (cf my response to parent
post).

Christophe

--
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.blogspot.com/ (en)


Reply all
Reply to author
Forward
0 new messages