2013-06-16 4 views
1

Leiningen과 Clojure를 사용하고 있으며 Clojure가 네임 스페이스를 올바르게 가져 오는 것이 왜 어려운지 이해할 수 없습니다.올바르게 Clojure에서 사용자 정의 클래스를 가져 오는 방법

: 나는합니다 ( lein 프로젝트의 SRC/디렉토리에) 다음을 입력 REPL에서

; namespace macro 
(ns animals.core 
    (:require animals.animal) 
    (:use animals.animal) 
    (:import (animals.animal Dog)) 
    (:import (animals.animal Human)) 
    (:import (animals.animal Arthropod)) 
    (:import (animals.animal Insect))) 

; make-animals will create a vector of animal objects 
(defn make-animals [] 
    (conj [] 
     (Dog. "Terrier" "Canis lupis familiaris") 
     (Human. "Human" "Homo sapiens") 
     (Arthropod. "Brown Recluse" "Loxosceles reclusa") 
     (Insect. "Fire Ant" "Solenopsis conjurata"))) 

; print-animals will print all the animal objects 
(defn print-animals [animals] 
    (doseq [animal animals] 
    (println animal))) 

; move-animals will call the move action on each animal 
(defn move-animals [animals] 
    (doseq [animal animals] 
    (animals.animal/move animal))) 

; entry to main program 
(defn -main [& args] 
    (let [animals make-animals] 
    (do 
     (println "Welcome to Animals!") 
     (println "-------------------") 
     (print-animals animals)))) 

그런 다음이이 내가 내 core.clj 파일에있는 것입니다

다음과 같은 오류입니다

user> (require 'animals.core) 
nil 
user> (animals.core/-main) 
ClassNotFoundException animals.core java.net.URLClassLoader$1.run (URLClassLoader.java:202) 

오케이 ... 뭐라 구요? 왜? 나는 때문에 -main의 오타에 다른 오류가 신선한 Leiningen 프로젝트에 붙여 넣기 코드와

(ns animals.animal) 

(defprotocol Animal 
    "A simple protocol for animal behaviors." 
    (move [this] "Method to move.")) 

(defrecord Dog [name species] 
    Animal 
    (move [this] (str "The " (:name this) " walks on all fours."))) 

(defrecord Human [name species] 
    Animal 
    (move [this] (str "The " (:name this) " walks on two legs."))) 

(defrecord Arthropod [name species] 
    Animal 
    (move [this] (str "The " (:name this) " walks on eight legs."))) 

(defrecord Insect [name species] 
    Animal 
    (move [this] (str "The " (:name this) " walks on six legs."))) 

답변

2

: 참고로

, 여기 내 animals 디렉토리도 파일 animal.clj입니다 (let [animals make-animals] ...)이 있어야한다 (let [animals (make-animals)] ...). 이러한 변화와 함께, 모두 잘 작동합니다 : 정확히 한 어딘가에 프로젝트 디렉토리 안에 뭐가로에서 lein repl를 호출 할 경우

user=> (require 'animals.core) 
nil 
user=> (animals.core/-main) 
Welcome to Animals! 
------------------- 
#animals.animal.Dog{:name Terrier, :species Canis lupis familiaris} 
#animals.animal.Human{:name Human, :species Homo sapiens} 
#animals.animal.Arthropod{:name Brown Recluse, :species Loxosceles reclusa} 
#animals.animal.Insect{:name Fire Ant, :species Solenopsis conjurata} 
nil 

덧붙여, 그것은 중요하지 않습니다.

require으로 처음 시도했을 때 네임 스페이스에 문제가있는 것으로 추측하고 REPL에서 일부 네임 스페이스로드 상태로 인해로드되지 않습니다. (require :reload 'animals.core)을 시도해보고 문제가 해결되지 않으면 REPL을 다시 시작하십시오. (다시 그것으로 실행하는 경우 당신은 또한 어딘가에 ClassNotFoundException까지 전체 REPL 상호 작용을 붙여 넣을 수 있습니다.)

또한, 귀하의 ns 형식에 대해 :

  1. 당신이해야 같은 둘 :require:use 이름 공간; :use 이미 :require입니다.

  2. 단일 :import 절 (실제로는 절당 하나의 절)을 사용하는 것이 더 일반적입니다. 예를 들어,

    (:import (animals.animal Dog Human Arthropod Insect)) 
    

    그것은 순전히 Clojure의 스타일의 문제이지만, ClojureScript에서 언어에 필요한 사실이다.

+1

이미 네임 스페이스가 필요한 경우 클래스를 가져올 필요가 없습니다. 각 레코드에는 접두사가 a 인 레코드 이름 인 2 개의 추가 함수가 정의되어 있습니다. '-> Record'는 생성자와 같이 동작하지만 함수입니다. 'map-> Record'는 속성 맵을 취합니다. 예를 들어,'(animals.core/-> Dog "Terrier" "Canis lupis familiaris")'를 사용할 수있게 해줄 것이며 Clojure 구현에서 코드를 더 이식성있게 만들 것이다. – deterb