Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does *allow-unresolved-vars* do in Clojure?

Tags:

clojure

Like there is no official document for it http://clojuredocs.org/clojure_core/clojure.core/allow-unresolved-vars

like image 548
Zhunping Zhang Avatar asked Nov 11 '22 03:11

Zhunping Zhang


1 Answers

Apologies -- this is not a complete answer. I haven't figured out everything about it yet.


*allow-unresolved-vars* is defined in RT.java:

final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.intern("*allow-unresolved-vars*"), F).setDynamic();

and used in Compiler.java:

    if(o == null)
        {
        if(RT.booleanCast(RT.ALLOW_UNRESOLVED_VARS.deref()))
            {
            return sym;
            }
        else
            {
            throw Util.runtimeException("Unable to resolve symbol: " + sym + " in this context");
            }
        }

So clearly, its use here is to decide whether or not an exception should be immediately thrown when an unresolved symbol is encountered.

You can mess with it like so:

myns.core=> (ns clojure.core)
nil

clojure.core=> oops!
CompilerException java.lang.RuntimeException: Unable to resolve symbol: oops! in this context, compiling:(/tmp/form-init1596111142512149454.clj:1:884) 

clojure.core=> (defn q [] (oops!))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: oops! in this context, compiling:(/tmp/form-init1596111142512149454.clj:1:12) 

clojure.core=> (def *allow-unresolved-vars* true)
Warning: *allow-unresolved-vars* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *allow-unresolved-vars* or change the name. (/tmp/form-init1596111142512149454.clj:1)
#'clojure.core/*allow-unresolved-vars*

clojure.core=> oops!
IllegalArgumentException UnresolvedVarExpr cannot be evalled  clojure.lang.Compiler$UnresolvedVarExpr.eval (Compiler.java:1771)
clojure.core=> 

clojure.core=> (defn q [] (oops!))
CompilerException java.lang.VerifyError: (class: clojure/core$q, method: invoke signature: ()Ljava/lang/Object;) Unable to pop operand off an empty stack, compiling:(form-init1596111142512149454.clj:1:1) 

But I haven't figured out a use yet, because unresolved variables still cause errors -- they're just different errors. Also, I don't understand the warning when re-def-ing it, because the warning says that it's not declared dynamic, whereas it looks to me as though it is declared dynamic in RT.java.

like image 166
Matt Fenwick Avatar answered Nov 15 '22 12:11

Matt Fenwick