Clojure名称空间无法访问

时间:2015-02-14 21:45:03

标签: clojure leiningen read-eval-print-loop

我正在尝试从库中加载两个名称空间“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异常,说“核心”命名空间不可用。但是从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错误。

2 个答案:

答案 0 :(得分:2)

尝试:

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

=> No such namespace: str

我也有点惊讶,因为ifwhen应该只评估适当分支的表达式主体,而不是触及其他表达式。我没想到假的命名空间错误。

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

至于你应该做什么,这段代码很时髦,我从来没有想过或看到有人在做类似的事情。除非有一些特定的理由这样做,解决方案很简单:将您的需求推到ns的最顶层。没有必要改变其他任何东西。

答案 1 :(得分:2)

我使用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)))