Clojure 为什么非全局作用域(let、def)内的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

尝试在内部别名ns以便能够在本地使用它,但在尝试使用别名时出现错误
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),而且它们不是并发安全的。