在repl中使用必需的命名空间

时间:2016-02-29 20:34:55

标签: clojure clojurescript

当我在clojure-script源文件中需要一个命名空间时,我可以在代码中使用它。

E.g:

(ns my.core
  (:require [mylib.core :as lib]))

(lib/my-f)

(def something 99)

但是,当我尝试在repl中调用(lib/my-f)时 - 通过(ns my.core)更改命名空间后 - 我无法访问它。相比之下,ns中的所有其他定义都是可访问的:例如上面示例中的something

有没有办法访问repl中的要求?或者我每次都必须在repl中手动要求它们?当然,这将非常繁琐。

2 个答案:

答案 0 :(得分:6)

如果使用ns更改ClojureScript REPL中的命名空间,则会将命名空间别名设置为与ns形式中使用的别名相匹配。

这是一个说明这个概念的例子:

$ java -jar cljs.jar -m cljs.repl.nashorn
To quit, type: :cljs/quit
cljs.user=> (ns foo.core (:require [clojure.string :as string]))

foo.core=> (string/starts-with? "abc" "a")
true
foo.core=> (ns bar.core)

bar.core=> (ns foo.core)

foo.core=> (string/starts-with? "abc" "a")
WARNING: No such namespace: string, could not locate string.cljs, string.cljc, or Closure namespace "" at line 1 <cljs repl>
WARNING: Use of undeclared Var string/starts-with? at line 1 <cljs repl>
ReferenceError: "string" is not defined

如果您使用in-ns REPL special更改为现有命名空间,则会保留别名:

$ java -jar cljs.jar -m cljs.repl.nashorn
To quit, type: :cljs/quit
cljs.user=> (ns foo.core (:require [clojure.string :as string]))

foo.core=> (string/starts-with? "abc" "a")
true
foo.core=> (ns bar.core)

bar.core=> (in-ns 'foo.core)
nil
foo.core=> (string/starts-with? "abc" "a")
true

一个有趣的相关方面:如果您使用require REPL特殊内容,它将在引擎盖下使用ns形式,并在保留现有别名的表单中加入特殊元素:

$ java -jar cljs.jar -m cljs.repl.nashorn
To quit, type: :cljs/quit
cljs.user=> (require '[clojure.string :as string])
nil
cljs.user=> (require '[clojure.string :as str])
nil
cljs.user=> (string/starts-with? "abc" "a")
true
cljs.user=> (str/starts-with? "abc" "a")
true

如果您感到好奇,这是:merge true meta:https://github.com/clojure/clojurescript/blob/r1.7.228/src/main/clojure/cljs/repl.cljc#L679

分析师很尊重它:https://github.com/clojure/clojurescript/blob/r1.7.228/src/main/clojure/cljs/analyzer.cljc#L1953

通过了解其工作原理,它应该提供一些深入了解为什么在REPL中直接评估ns形式(没有merge元)会导致别名被清除的原因。

简而言之,请避免直接使用ns special来更改REPL中的命名空间。而是使用它在REPL中创建新的命名空间,同时指定任何必需的命名空间。

使用in-ns REPL special切换到现有命名空间。它还可以用于创建新的命名空间。

使用require将命名空间加载到REPL中,然后使用in-ns切换到它们。

答案 1 :(得分:1)

只要您在使用requirens切换到命名空间之前in-ns命名空间,这一切都可以正常工作。对我来说令人费解的是something是可访问的,这意味着您的代码已被加载:这应该意味着它的名称空间形式也被评估,因此您应该可以使用其别名。你确定你是从一个新鲜的状态做到这一点,并且没有,比如说,独立定义something吗?仔细检查:

  1. 关闭repl
  2. 开始新的repl
  3. (require 'my.core)
  4. (in-ns 'my.core)
  5. 检查问题中的内容是否仍然存在。你仍然可以访问something?你还能访问lib/my-f吗?我预测这两件事中的一件会改变:你应该既不能访问,也不能两者都访问。
相关问题