无法访问 Clojure 命名空间

Clojure namespace not accessible

我正在尝试从库 "spurious-aws-sdk-helper" 加载两个名称空间(顺便说一下,我已经在本地安装了 - 这是我在部署到 Clojars 之前对其进行测试)。我正在从 if 语句中加载命名空间。

加载命名空间后,我将调用一个由加载的命名空间之一提供的函数。

问题是,当通过 lein ring server 执行代码时,我收到一个 Java 异常,通知我我尝试访问的命名空间不可用。

但是如果我 运行 lein repl 然后 (use 'spurious-clojure-example.routes.home) 相关的顶级命名空间;然后 (require '[spurious-aws-sdk-helper.core :as core]) 命名空间 - 就像我稍后将链接到的代码中演示的那样 - 然后命名空间将可用并且随后对函数的调用不会出错?

我不确定这是否是那些具有误导性的错误之一,事实上它不是我试图要求的名称空间,而是它内部的某些东西才是问题所在?但如果那是真的那么为什么在 lein repl 内由我自己手动调用时它会起作用?

我指的代码是:https://github.com/Integralist/spurious-clojure-example/blob/baseline/src/spurious_clojure_example/routes/home.clj#L9-L10

(ns spurious-clojure-example.routes.home
  (:use [amazonica.aws.s3])
  (:require [compojure.core :refer :all]
            [environ.core :refer [env]]
            [spurious-clojure-example.views.layout :as layout]))

(if (env :debug)
  (do
    (require '[spurious-aws-sdk-helper.core :as core])
    (require '[spurious-aws-sdk-helper.utils :refer [endpoint cred]])
    (core/configure {:s3  "test-bucket4"
                     :sqs "test-queue4"
                     :ddb (slurp "./resources/config/schema.yaml")})))

(def bucket-path "news-archive/dev/election2014-council_title")

(def content
  (apply str (line-seq
               (clojure.java.io/reader
                 (:object-content
                   (get-object (cred (endpoint :spurious-s3)) :bucket-name "shared" :key bucket-path))))))

(defn home []
  (layout/common [:h1 content]))

(defroutes home-routes
  (GET "/" [] (home)))

(core/configure ...) 调用触发了 Java 异常,提示 "core" 命名空间不可用。但是 运行使用 lein repl 中的以下代码可以正常工作...

(use 'spurious-clojure-example.routes.home)
(require '[spurious-aws-sdk-helper.core :as core])
(core/configure ...rest of code...)

更新 1:

为了澄清,我已将代码更新如下...

(when (env :debug)
  (require '[spurious-aws-sdk-helper.core :as core])
  (require '[spurious-aws-sdk-helper.utils :refer [endpoint cred]])
  (core/configure
   {:s3 "test-bucket7"
    :sqs "test-queue9"
    :ddb (slurp "./resources/config/schema.yaml")}))

...当 运行在 REPL 中使用它时它工作正常。

问题是当 运行通过 lein ring server 连接它时。

我已经开始阅读有关 (ns-resolve) 的文章:http://technomancy.us/143

但是它建议的解决方案:(ns-resolve 'core 'configure) 没有用;它只是抛出了一个 Unable to resolve symbol: core in this context 错误。

尝试过:

(when true ; also tried with false
  (require '[clojure.string :as str])
  (str/split "Clojure is awesome!" #" "))

=> No such namespace: str

我也有点惊讶,因为 ifwhen 应该只计算适当分支的表达式主体,而不触及其他表达式。我没想到 false 会出现命名空间错误。

更令人惊讶的是,我没想到 true 也会出现命名空间错误。我猜这是一些 java 编译的东西,甚至在代码评估之前就试图解析命名空间。我不知道具体原因。

至于你应该做什么,这段代码很时髦,我从未想过或见过任何人做过类似的事情。除非有某些特定原因需要这样做,否则解决方案很简单:将您的需求推到 ns 中的最顶端。无需更改任何其他内容。

我用 lein new compojure-app 创建了一个应用程序,当 :debug 值为真时,需要 clojure.string :as str 然后打印一些东西到 shell.

下面的代码通过 lein ring server 运行。我用 :debugtruefalse 测试了它。我在你的例子中看到,你使用 environ 所以,我把 {:debug true}{:debug false} 放在 .lein-env 中。


    (ns integralist.handler
      (:require [compojure.core :refer [defroutes routes]]
                [ring.middleware.resource :refer [wrap-resource]]
                [ring.middleware.file-info :refer [wrap-file-info]]
                [hiccup.middleware :refer [wrap-base-url]]
                [compojure.handler :as handler]
                [compojure.route :as route]
                [integralist.routes.home :refer [home-routes]]
                [environ.core :refer [env]]))

    (when (env :debug)
      (require '[clojure.string :as str]))

    (when (env :debug)
      (defn it-works! []
        (println "It works!:" (str/split "Clojure is Awesome" #" "))))

    (defn init []
      (println "integralist is starting")
      (when (env :debug)
        (it-works!)))

    (defn destroy []
      (println "integralist is shutting down"))

    (defroutes app-routes
      (route/resources "/")
      (route/not-found "Not Found"))

    (def app
      (-> (routes home-routes app-routes)
          (handler/site)
          (wrap-base-url)))