Clojure 为什么非全局作用域(let、def)内的ns别名不起作用?
尝试在内部别名ns以便能够在本地使用它,但在尝试使用别名时出现错误Clojure 为什么非全局作用域(let、def)内的ns别名不起作用?,clojure,namespaces,Clojure,Namespaces,尝试在内部别名ns以便能够在本地使用它,但在尝试使用别名时出现错误CompilerException java.lang.RuntimeException:没有这样的命名空间:sss (ns core (:require [clojure.set] [clojure.string]) ) (let [] (alias 'sss 'clojure.string) (println (ns-aliases *ns*) "hi1") (p
CompilerException java.lang.RuntimeException:没有这样的命名空间:sss
(ns core
(:require [clojure.set]
[clojure.string])
)
(let []
(alias 'sss 'clojure.string)
(println (ns-aliases *ns*) "hi1")
(println (sss/capitalize "hONdURas"))
;(println (clojure.string/capitalize "hONdURas")) ;;this works
(ns-unalias *ns* 'sss)
(+ 1 2)
)
(println (ns-aliases *ns*))
(别名…)不必是顶级的。clojure的工作方式是有一种叫做reader的东西,它获取文本数据并将其转换为数据结构,作为编译器的输入。看
在使用之前,必须为读取器定义代码中引用的任何名称空间。(与函数类似)
那么在
(let []
(alias 'sss 'clojure.string)
(println (sss/capitalize "aaa")))
读卡器试图打开时,尚未分配别名
(sss/capitalize)
进入数据。不特定于
let
<代码>(def testd(do(别名“sss”clojure.string)(sss/trim“”)和(fn[](别名“sss”clojure.string)(sss/trim“”)
是相同的。看起来alias
必须是顶级的。遗憾的是:(我希望在每次选择中使用类似于SQL的别名,我可以对非常不同的表使用相同的别名,因为它们对于每个查询都是本地的。)非常奇怪,只需放入(别名“sss”clojure.string)
不会导致任何错误有趣的是,别名正在注册:(let[](别名“b”clojure.string)(println“NS:(NS别名*NS*))
输出NS:{b#object[clojure.lang.Namespace 0x66bd2083 clojure.string]]
。但是,如果您尝试使用别名,整个过程都会失败,在println
运行之前出现编译器异常。这看起来几乎像是一个bug。@carcigenitate(let[…)
并不总是与(do…
相同。在文件的顶层,每个(do…)中的子表达式
单独编译和执行。相反,(让[…])
遵循通常的求值规则,编译整个表达式(包括所有子表达式)立即进行评估。如果您正在更改环境,例如添加命名空间别名,这可能会产生影响。您的意思是alias
也根据需要定义[temporal]命名空间吗?(temporal,因为ns unalias
可以完成)嗯,您所说的[temporal]是什么意思?(别名…)就像:在require中一样,似乎我理解这个问题不是在alias中,而是在阅读sss/
中。好吧,我希望有类似smth的(ns的sss)对于别名:/另外,请尝试使用ns-interns
,它返回所有ns符号的映射,而不是逐个解析它们。在局部范围上下文中考虑var名称空间不是惯用的clojure,而且也没有真正的意义。别名指向var名称空间,这是依赖项解析的机制。var名称根据定义,paces相当于使用本地别名的模块作用域,类似于在let中执行(def…)或(defn),而且它们不是并发安全的。