remove-ns before loading lib?

27 views
Skip to first unread message

Stephen C. Gilardi

unread,
Aug 31, 2008, 8:12:07 PM8/31/08
to Clojure
One of the downsides of interactive development and testing using the REPL is the fact that an old definitions in a lib's namespace can linger in memory after its source code has been deleted from the lib. One can relaunch Clojure to be sure of clearing that situation, but that often loses some desirable context. I'm proposing a change to make relaunching Clojure for that purpose unnecessary.

With the new clojure/require and clojure/use, we've introduced a suggested, preferred, best-supported way of working with Clojure in which there's a one-to-one correspondence between a lib namespace and the lib that defines it.  The enclosed patch would ensure that any old definitions in a lib namespace are discarded before loading the lib: the namespace would be built up from scratch with each load. Putting the 'remove-ns call at the location I suggest would allow ":reload" and ":reload-all" to support this "from scratch" behavior as well. (:reload-all is especially useful from the REPL.)

There may still be situations where other code can hold onto an old definition across a reload but this change will cover the vast majority of cases easily and reliably.

Would this be a good change?

--Steve

Index: boot.clj
===================================================================
--- boot.clj (revision 1013)
+++ boot.clj (working copy)
@@ -3045,6 +3045,7 @@
   namespace exists after loading. If require, records the load so any
   duplicate loads can be skipped."
   [lib need-ns require]
+  (remove-ns lib)
   (load-resources (root-resource lib))
   (throw-if (and need-ns (not (find-ns lib)))
             "namespace '%s' not found after loading '%s'"
 

Rich Hickey

unread,
Aug 31, 2008, 10:11:47 PM8/31/08
to Clojure


On Aug 31, 8:12 pm, "Stephen C. Gilardi" <squee...@mac.com> wrote:
> One of the downsides of interactive development and testing using the
> REPL is the fact that an old definitions in a lib's namespace can
> linger in memory after its source code has been deleted from the lib.
> One can relaunch Clojure to be sure of clearing that situation, but
> that often loses some desirable context. I'm proposing a change to
> make relaunching Clojure for that purpose unnecessary.
>
> With the new clojure/require and clojure/use, we've introduced a
> suggested, preferred, best-supported way of working with Clojure in
> which there's a one-to-one correspondence between a lib namespace and
> the lib that defines it. The enclosed patch would ensure that any old
> definitions in a lib namespace are discarded before loading the lib:
> the namespace would be built up from scratch with each load. Putting
> the 'remove-ns call at the location I suggest would allow ":reload"
> and ":reload-all" to support this "from scratch" behavior as well.
> (:reload-all is especially useful from the REPL.)
>
> There may still be situations where other code can hold onto an old
> definition across a reload but this change will cover the vast
> majority of cases easily and reliably.
>
> Would this be a good change?
>

No, because code that used the namespace will then be bound to
orphaned vars. New/fixed definitions under those names will create new
vars, and thus not update referencing code.

So, only namespaces that are not referenced by anything else can be
safely removed - it's a very special-purpose operation.

Rich

Stephen C. Gilardi

unread,
Aug 31, 2008, 11:00:14 PM8/31/08
to clo...@googlegroups.com
On Aug 31, 2008, at 10:11 PM, Rich Hickey wrote:
On Aug 31, 8:12 pm, "Stephen C. Gilardi" <squee...@mac.com> wrote:
There may still be situations where other code can hold onto an old
definition across a reload but this change will cover the vast
majority of cases easily and reliably.

Or, as it turns out not the vast majority at all. Whoops!


No, because code that used the namespace will then be bound to
orphaned vars. New/fixed definitions under those names will create new
vars, and thus not update referencing code.

I understand, thanks. I recall now we've discussed "transactional loading" in the past and you decided to pass.

Would it work to compare the set of ns-publics for the namespace before and after the load and unbind-root the vars that were present before but are not present after? I'm not proposing it, just trying to understand how things work.

--Steve

Reply all
Reply to author
Forward
0 new messages