1

私は Clojure に比較的慣れておらず、 Seven Languages in Seven Weeksの Clojure の章を読んでいますが、本のこのコードが機能しない理由がわかりません。Leiningen と Clojure バージョン 1.5.1 を使用しています。注意深くチェックした後にわかる限り、本に書かれているとおりにコードを正確に入力しました。

コードは次のとおりです。

(ns seven-languages.compass)

(defprotocol Compass
    (direction [c])
    (left [c])
    (right [c]))

(def directions [:north :east :south :west])

(defn turn [base amount]
    (rem (+ base amount) (count directions)))

(defrecord SimpleCompass [bearing]
    Compass
    (direction [_] (directions bearing))
    (left [_] (SimpleCompass. (turn bearing 3)))
    (right [_] (SimpleCompass. (turn bearing 1)))

    Object
    (toString [this] (str "[" (direction this) "]")))

ディレクトリ ~/clojure/seven-languages (~/clojure で「lein new Seven-languages」を実行して作成) 内から「lein repl」を実行しています。このディレクトリに対して、私の .clj ファイルは src/seven_languages にあります。これまでのところ、入力してreplから正常にインポートして使用することができました(use 'seven-languages.filenamehere)

上記のコードを src/seven_languages/compass.clj として保存した後、これを REPL から実行します。

user=> (use 'seven-languages.compass)
nil

しかし、SimpleCompass の「インスタンス」を定義しようとすると、本とまったく同じように入力すると、次のようになります。

user=> (def c (SimpleCompass. 0))

CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: SimpleCompass, compiling:(NO_SOURCE_PATH:1:8)

を使用してファイルのロードも試み(load-file "src/seven_languages/compass.clj")ましたが、同じ結果が得られました。実際の読み込みは期待どおりに機能しているように見えたので、 7 週間で 7 つの言語が書かれた以降のバージョンの Clojure では、defprotocol または defrecord の動作に何らかの変更があったのではないかと思います。Clojure の章の導入部で、著者は次のように書いています。

このコードが正しく動作しない理由を誰か教えてください。バージョンの問題である場合、Clojure 1.5.1 用にこのコードをどのように更新しますか?

編集:ああ!これを見つけた後、私はそれを理解しました:
Clojure - deftypeは無視されました - テストでクラス名を解決できません

名前空間の問題です。これは、7LI7W が作成されたバージョン 1.2 からの変更であると推測しています。何らかの理由で、インポートされたファイルの関数は「自動的に処理」されるため、直接使用できますが、型は自動的に処理されません。タイプへのフル パスを含める必要があり、ハイフンではなくアンダースコアを含む実際のパスを使用していることを確認してください。SimpleCompassフルパスに置き換えることで、コードが機能するようになりましたseven_languages.compass.SimpleCompass

user=> (def c (seven_languages.compass.SimpleCompass. 0))
#'user/c
user=> c
#seven_languages.compass.SimpleCompass{:bearing 0}
user=> (left c)
#seven_languages.compass.SimpleCompass{:bearing 3}
user=> (right c)
#seven_languages.compass.SimpleCompass{:bearing 1}
4

1 に答える 1