3

2 つのテスト ファイルにまったく同じコードを含む 2 つの「lein」プロジェクトがあります。

... clojure.set/union ...

最初のプロジェクトは正常にコンパイルおよび実行されます。2番目のものは次のようにエラーになります:

Exception in thread "main" java.lang.ClassNotFoundException: clojure.set, compiling:(foo/bar.clj:14)
...
Caused by: java.lang.ClassNotFoundException: clojure.set
...

:use明示的に追加した場合にのみ、2番目のプロジェクトを実行できますbar.clj

(:use clojure.set)

ただし、最初のプロジェクトにはこのステートメントがありません。なぜ異なる行動をするのですか?

更新

例外が発生していない最初のプロジェクトには、次の宣言がありますproject.clj

:eval-in-leiningen true
4

2 に答える 2

4

ローカル シンボルがその名前空間内の名前を参照するようにする場合は、名前空間の使用を宣言するだけで済みます。それ以外の場合は、使用する各変数の完全な名前を綴ることができます。http://clojure.org/namespacesの最初のページを参照してください。

通常の関数は通常 s に格納されており、名前を完全にスペルアウトするか、それを囲む名前空間にシンボルを配置varすることでアクセスできます。例として、bar と呼ばれる完全に空の名前空間から始めることができます。Clojure のコア関数から始めることさえできません。(clojure.core/+ 1 2)refer

foo> (in-ns 'bar)
#<Namespace bar>
bar> (+ 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: + in this context, compiling:(NO_SOURCE_PATH:1)   

+ただし、それを含むの完全な名前をスペルアウトすれば、関数を使用できますvar

bar> (clojure.core/+ 1 2)
3

次に、シンボル+が clojure.core で参照するのと同じ var を参照するようにするには、次のように呼び出します。refer

bar> (clojure.core/refer 'clojure.core)
nil
bar> (+ 1 2)
3


エラーに関しては、このような状況は次の場合に発生する傾向があります。

  • その名前空間にいる間に実行した(use 'clojure.set)(require 'clojure.set)、REPL から
  • clojure.set から関数を呼び出すコードが実際には呼び出されていないため、エラーが表示されません。
  • (ns foo.bar (:use clojure.clj))一方のプロジェクトではファイルの先頭にあるフォームで宣言され、もう一方のプロジェクトでは宣言されていません
于 2012-12-29T00:39:08.940 に答える
3

Clojure の依存関係は、他のほとんどの動的言語と同じように動作します。名前空間を明示的に要求するまでは、名前空間がランタイムに読み込まれていないため、そこからのシンボルは使用できません。ただし、名前空間が読み込まれると、そのシンボルはすべての名前空間から利用できるようになります。この不一致は、ファイルがランタイムに読み込まれる順序の詳細に起因します。

名前空間の依存関係の問題の他の側面は、外部名前空間シンボルを逆参照する利便性のレベルのみを扱います。

  • フルネームの代わりに使用する名前空間プレフィックスを宣言できます。

    (require [clojure.string :as s])

    これにより、(s/join "," coll)

  • 外部ネームスペースから特定のシンボルをホームネームスペースに参照できます。これにより、ローカル シンボルが外部の名前空間内の同じ名前の対応するシンボルにバインドされます。

    (require [clojure.string :refer [join]])

    あなたに与える(join "," coll)

  • プレフィックスを宣言することも、特定のシンボルを参照することもできます。

    (require [clojure.string :as s :refer [join]])

    あなた(join "," coll)だけでなく、(s/join "," coll)

  • 名前空間全体をホーム名前空間に参照できます。

    (require [clojure.string :refer :all])

注: デモの構文は、(ns ...)フォーム内でのみ機能します。requireをスタンドアロン形式で使用する場合、すべてのシンボルを明示的に引用符で囲む必要があります。

ご覧のとおり、(Clojure 1.4 の時点で) 必要なのはrequireだけであり、useは、プレフィックスを宣言する必要がない場合のちょっとした便利な手段にすぎません。

(use clojure.string)と同じです(require [clojure.string :refer :all])

(use [clojure.string :only [join]])と同じ(require [clojure.string :refer [join]])です。

于 2012-12-30T12:04:10.013 に答える