In a common lisp setting a symbol could be represented
as vector containing slots. Two of the slots are of interest,
the function slot and the value slot. The symbol looks like:

--------------------------------------------------------------
| function | value | package | alist | ....
-------------------------------------------------------------


You can place a function in either the function or value slots.
The (defun...) function places it in the symbol's function slot.

You can define a naked function using lambda thus:
(lambda () 5)

You can execute this function thus:
(funcall (lambda () 5)) ==> 5

Now you can assign this function to the symbol A in two ways:

(setf A (lambda () 'value-slot))                      ;fill the value slot
(setf (symbol-function A) (lambda () 'function-slot)) ;fill the function slot

The first fills in the value-slot of A. You can call it with:
(funcall A) ==> value-slot

The second fills in the function-slot of A. You can call it with:
(A) ==> function-slot

So now you take a new symbol B with both a value-slot and a function-slot.
You want to "copy" something about the symbol A into B.
What is it you expect to copy?

(setf B A)
           == copy the value slot of A into the value-slot of B
              so that (funcall B) ==> value-slot
(setf B (symbol-function 'A))
           == copy the function slot of A into the value-slot of B
               so that (funcall B) ==> function-slot
(setf (symbol-function 'B) A)
           == copy the value-slot of A into the function-slot of B
              so that (B) ==> value-slot
(setf (symbol-function 'B) (symbol-function 'A))
           == copy the function-slot of A into the function-slot of B
              so that (B) ==> function-slot

Subsequent changes to A (either the function-slot or the value-slot)
will not affect the behavior of B. To do that you need to define B
in terms of A, such as:

(defun B () (A))         == call the function-slot of A
(defun B () (funcall A)) == call the value-slot of A

Which of the many behaviors were you expecting?

On 11/17/2010 7:39 AM, Alyssa Kwan wrote:
Hi Alex,

I understand exactly why this situation exists.  I just think the
behavior is unexpected.  When I create a function with a dynamic
binding, I expect the function to keep a reference to the *name*, not
the var that the name resolves to at compile/clinit time.  Using with-
bindings* seems terribly unsupported as well.

I guess the question is:  what do other people expect?  Am I alone in
thinking that this is unexpected and undesirable?

Thanks,
Alyssa Kwan

On Nov 17, 3:04 am, Alex Osborne<a...@meshy.org>  wrote:
Hi Alyssa,

Alyssa Kwan<alyssa.c.k...@gmail.com>  writes:
ns-unmap isn't typically used.  But for durability, we can think of
JVM shutdown/startup as unmapping everything and starting fresh.
Therefore, expected behavior for ns-unmap should be the same as
behavior for deserializing and loading an object after a new JVM
startup.
I think the point that you're missing is that vars are just plain old
first class objects.  This includes being managed by the garbage
collector so they'll continue to exist until all references to them are
released.  You can pass them around, put them in vectors etc.

  Here's another issue I ran into:
=>  (def a 1)
#'user/a
=>  (defn b [] a)
#'user/b
When you compile this, a reference to the var #'user/a is embedded in
your b function.  This reference is directly to the var object.

So far so good...
=>  (ns-unmap *ns* 'a)
nil
=>  a
java.lang.Exception: Unable to resolve symbol: a in this context
=>  (b)
2
The var has been unmapped from the namespace, but it still exists
because the function b has a reference to it.  Vars don't need to live
in a namespace.  For example, the "with-local-vars" macro creates a
"local" var which doesn't belong to a namespace.



=>  (binding [a 3]
      (b))
java.lang.Exception: Unable to resolve var: a in this context
So what's the expected behavior here?  I would think that after a is
unmapped, b should no longer work.  Instead, it's hanging onto a with
the last value.
The var still exists, b holds a reference to it.

And the binding form doesn't work anymore, so there's
no way to dynamically bind over it.  It's like a weird hybrid of
lexical and dynamic binding...
The only reason this is erroring is that the symbol 'a can no longer be
mapped to your var.

Actually there is a way to dynamically bind over a var which has been
unmapped, all you need is a reference to it:

user>  (def a 1)
#'user/a
user>  (def my-a #'user/a)
#'user/my-a
user>  (defn b [] a)
#'user/b
user>  (ns-unmap *ns* 'a)
nil
user>  (b)
1
user>  (with-bindings* {my-a 30} #(b))
30

--
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
Note that posts from new members are moderated - please be patient with your 
first post.
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