ClojureScript

ns-unmap doesn't work on refers from cljs.core

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: 1.7.145
  • Fix Version/s: 1.9.671
  • Component/s: None
  • Labels:
  • Patch:
    Code

Description

In ClojureScript, using ns-unmap on a symbol from cljs.core doesn't exclude it from the current namespace. Note that both a function and a macro still exist, even after unmapping:

To quit, type: :cljs/quit  
cljs.user=> (ns-unmap 'cljs.user 'when) ;; macro
true  
cljs.user=> (ns-unmap 'cljs.user 'not)  ;; function
true  
cljs.user=> (when 1 2)  
2  
cljs.user=> (not false)  
true  

This differs from the behavior of Clojure's ns-unmap. Note the appropriate errors when attempting to use unmapped symbols:

Clojure 1.7.0-beta1
user=> (ns-unmap 'user 'when) ;; macro
nil
user=> (ns-unmap 'user 'not)  ;; function
nil
user=> (when 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: when in this context, compiling:(NO_SOURCE_PATH:11:1) 
user=> (not false)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: not in this context, compiling:(NO_SOURCE_PATH:12:1) 

Somehow ClojureScript's ns-unmap needs to add the symbol to the current namespace's :excludes set. Note that the def special form does this already (after it displays a warning).

We have two solutions. 0001 extends the ns form's :merge behavior to support :excludes, and then uses this in ns-unmap. If the enhancement to ns isn't wanted, patch 0002 changes ns-unmap to update :excludes directly.

Activity

Chouser made changes -
Field Original Value New Value
Attachment 0001-CLJS-1237-ns-unmap-adds-to-namespace-s-excludes.patch [ 14099 ]
Description In ClojureScript, using {{ns-unmap}} on a symbol from {{cljs.core}} doesn't exclude it from the current namespace. Note the warning from {{def}}:

{noformat}
To quit, type: :cljs/quit
cljs.user=> (ns-unmap 'cljs.user 'first)
true
cljs.user=> (def first 1)
WARNING: first already refers to: cljs.core/first being replaced by: cljs.user/first at line 1 <cljs repl>
1
{noformat}

This differs from the behavior of Clojure's {{ns-unmap}}. Note the lack of warning from {{def}} below:

{noformat}
Clojure 1.7.0-beta1
user=> (ns-unmap 'user 'first)
nil
user=> (def first 1)
#'user/first
{noformat}

Somehow {{ns-unmap}} needs to add the symbol to the current namespace's {{:excludes}} set. Note that the {{def}} special form does this already (after it displays the warning).

Our solution is to take advantage of {{ns}} form's {{:merge}} behavior by first extending that behavior to support {{:excludes}} which {{ns-unmap}} then uses.
In ClojureScript, using {{ns-unmap}} on a symbol from {{cljs.core}} doesn't exclude it from the current namespace. Note that both a function and a macro still exist, even after unmapping:

{noformat}
To quit, type: :cljs/quit
cljs.user=> (ns-unmap 'cljs.user 'when) ;; macro
true
cljs.user=> (ns-unmap 'cljs.user 'not) ;; function
true
cljs.user=> (when 1 2)
2
cljs.user=> (not false)
true
{noformat}

This differs from the behavior of Clojure's {{ns-unmap}}. Note the appropriate errors when attempting to use unmapped symbols:

{noformat}
Clojure 1.7.0-beta1
user=> (ns-unmap 'user 'when) ;; macro
nil
user=> (ns-unmap 'user 'not) ;; function
nil
user=> (when 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: when in this context, compiling:(NO_SOURCE_PATH:11:1)
user=> (not false)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: not in this context, compiling:(NO_SOURCE_PATH:12:1)
{noformat}

Somehow ClojureScript's {{ns-unmap}} needs to add the symbol to the current namespace's {{:excludes}} set. Note that the {{def}} special form does this already (after it displays a warning).

Our solution is to take advantage of {{ns}} form's {{:merge}} behavior by first extending that behavior to support {{:excludes}} which {{ns-unmap}} then uses.
Patch Code [ 10001 ]
Chouser made changes -
Attachment 0002-CLJS-1237-ns-unmap-adds-to-namespace-s-excludes.patch [ 14100 ]
Description In ClojureScript, using {{ns-unmap}} on a symbol from {{cljs.core}} doesn't exclude it from the current namespace. Note that both a function and a macro still exist, even after unmapping:

{noformat}
To quit, type: :cljs/quit
cljs.user=> (ns-unmap 'cljs.user 'when) ;; macro
true
cljs.user=> (ns-unmap 'cljs.user 'not) ;; function
true
cljs.user=> (when 1 2)
2
cljs.user=> (not false)
true
{noformat}

This differs from the behavior of Clojure's {{ns-unmap}}. Note the appropriate errors when attempting to use unmapped symbols:

{noformat}
Clojure 1.7.0-beta1
user=> (ns-unmap 'user 'when) ;; macro
nil
user=> (ns-unmap 'user 'not) ;; function
nil
user=> (when 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: when in this context, compiling:(NO_SOURCE_PATH:11:1)
user=> (not false)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: not in this context, compiling:(NO_SOURCE_PATH:12:1)
{noformat}

Somehow ClojureScript's {{ns-unmap}} needs to add the symbol to the current namespace's {{:excludes}} set. Note that the {{def}} special form does this already (after it displays a warning).

Our solution is to take advantage of {{ns}} form's {{:merge}} behavior by first extending that behavior to support {{:excludes}} which {{ns-unmap}} then uses.
In ClojureScript, using {{ns-unmap}} on a symbol from {{cljs.core}} doesn't exclude it from the current namespace. Note that both a function and a macro still exist, even after unmapping:

{noformat}
To quit, type: :cljs/quit
cljs.user=> (ns-unmap 'cljs.user 'when) ;; macro
true
cljs.user=> (ns-unmap 'cljs.user 'not) ;; function
true
cljs.user=> (when 1 2)
2
cljs.user=> (not false)
true
{noformat}

This differs from the behavior of Clojure's {{ns-unmap}}. Note the appropriate errors when attempting to use unmapped symbols:

{noformat}
Clojure 1.7.0-beta1
user=> (ns-unmap 'user 'when) ;; macro
nil
user=> (ns-unmap 'user 'not) ;; function
nil
user=> (when 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: when in this context, compiling:(NO_SOURCE_PATH:11:1)
user=> (not false)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: not in this context, compiling:(NO_SOURCE_PATH:12:1)
{noformat}

Somehow ClojureScript's {{ns-unmap}} needs to add the symbol to the current namespace's {{:excludes}} set. Note that the {{def}} special form does this already (after it displays a warning).

We have two solutions. 0001 extends the {{ns}} form's {{:merge}} behavior to support {{:excludes}}, and then uses this in {{ns-unmap}}. If the enhancement to {{ns}} isn't wanted, patch 0002 changes {{ns-unmap}} to update {{:excludes}} directly.
Hide
David Nolen added a comment -

The second patch is preferred. However it seems the second patch is too permissive. The :excludes logic should only be applied if the symbol identifies a core macro or fn.

Show
David Nolen added a comment - The second patch is preferred. However it seems the second patch is too permissive. The :excludes logic should only be applied if the symbol identifies a core macro or fn.
David Nolen made changes -
Fix Version/s Next [ 10362 ]
Hide
Chouser added a comment -

The ns form's own :refer-clojure :exclude accepts arbitrary symbols and adds them to the namespace's :excludes set, which seems like the same permissiveness problem. Do you want a patch that addresses the permissiveness of both ns and ns-unmap in this ticket, or should such a patch go in a new ticket?

Show
Chouser added a comment - The ns form's own :refer-clojure :exclude accepts arbitrary symbols and adds them to the namespace's :excludes set, which seems like the same permissiveness problem. Do you want a patch that addresses the permissiveness of both ns and ns-unmap in this ticket, or should such a patch go in a new ticket?
Hide
David Nolen added a comment -

New ticket to fix the bug that :exclude doesn't check the symbol list for cljs.core declared vars, and an updated patch here please.

Show
David Nolen added a comment - New ticket to fix the bug that :exclude doesn't check the symbol list for cljs.core declared vars, and an updated patch here please.
David Nolen made changes -
Affects Version/s Next [ 10362 ]
Affects Version/s 0.0-3196 [ 10355 ]
Fix Version/s Backlog [ 10363 ]
Fix Version/s Next [ 10362 ]
David Nolen made changes -
Affects Version/s Next [ 10363 ]
Affects Version/s 0.0-3255 [ 10362 ]
Fix Version/s Backlog [ 10365 ]
Fix Version/s Next [ 10363 ]
David Nolen made changes -
Fix Version/s Backlog [ 10366 ]
Fix Version/s Next [ 10365 ]
David Nolen made changes -
Affects Version/s 1.7.28 [ 10366 ]
Affects Version/s 0.0-3269 [ 10363 ]
Fix Version/s Next [ 10450 ]
Fix Version/s 1.7.28 [ 10366 ]
David Nolen made changes -
Affects Version/s Next [ 10450 ]
Affects Version/s 1.7.28 [ 10366 ]
Fix Version/s Backlog [ 10651 ]
Fix Version/s Next [ 10450 ]
David Nolen made changes -
Affects Version/s Next [ 10651 ]
Affects Version/s 1.7.48 [ 10450 ]
Fix Version/s Backlog [ 10653 ]
Fix Version/s Next [ 10651 ]
David Nolen made changes -
Priority Major [ 3 ] Minor [ 4 ]
David Nolen made changes -
Fix Version/s Next [ 10751 ]
Fix Version/s 1.7.228 [ 10653 ]
David Nolen made changes -
Fix Version/s Backlog [ 10851 ]
Fix Version/s Next [ 10751 ]
David Nolen made changes -
Fix Version/s Next [ 11055 ]
Fix Version/s 1.9.293 [ 10851 ]
David Nolen made changes -
Fix Version/s 1.9.655 [ 11055 ]
Fix Version/s Backlog [ 11154 ]
David Nolen made changes -
Fix Version/s 1.9.660 [ 11154 ]
Fix Version/s Backlog [ 11359 ]

People

  • Assignee:
    Unassigned
    Reporter:
    Chouser
Vote (0)
Watch (2)

Dates

  • Created:
    Updated: