Getting Vars to bind properly across multiple files
I am just learning Clojure and am having trouble moving my code into different files.
I keep detting this error from the appnrunner.clj -
Exception in thread "main" java.lang.Exception: Unable to resolve symbol: -run-application in this context
It seems to be finding the namespaces fine, but then not seeing the Vars as being bound... Any idea how to fix this?
Here's my code:
APPLICATION RUNNER -
(ns src/apprunner
(:use src/functions))
(def input-files [(resource-path "a.txt") (resource-path "b.txt") (resource-path "c.txt")])
(def output-file (resource-path "output.txt"))
(defn run-application []
(sort-files input-files output-file))
(run-application)
APPLICATION FUNCTIONS -
(ns src/functions
(:use clojure.contrib.duck-streams))
(defn flatten [x]
(let [s? #(instance? clojure.lang.Sequential %)]
(filter
(complement s?)
(tree-seq s? seq x))))
(defn resource-path [file]
(str "C:/Users/Alex and Paula/Documents/SoftwareProjects/MyClojureApp/resources/" file))
(defn split2 [str delim]
(seq (.split str delim)))
(defstruct person :first-name :last-name)
(defn read-file-content [file]
(apply str
(interpose "\n" (read-lines file))))
(defn person-from-line [line]
(let [sections (split2 line " ")]
(struct person (first sections) (second sections))))
(defn formatted-for-display [person]
(str (:first-name person) (.toUpperCase " ") (:last-name person)))
(defn sort-by-keys [struct-map keys]
(sort-by #(vec (map % [keys])) struct-map))
(defn formatted-output [persons output-number]
(let [heading (str "Output #" output-number "\n")
sorted-persons-for-output (a开发者_如何学JAVApply str (interpose "\n" (map formatted-for-display (sort-by-keys persons (:first-name :last-name)))))]
(str heading sorted-persons-for-output)))
(defn read-persons-from [file]
(let [lines (read-lines file)]
(map person-from-line lines)))
(defn write-persons-to [file persons]
(dotimes [i 3]
(append-spit file (formatted-output persons (+ 1 i)))))
(defn sort-files [input-files output-file]
(let [persons (flatten (map read-persons-from input-files))]
(write-persons-to output-file persons)))
You're not naming your namespaces correctly!
You should do something like this instead:
;;; in file src/apprunner/core.clj
;;; (namespace names should contain at least one dot for things
;;; not to go into the default package... or some such thing)
(ns apprunner.core
(:use apprunner.functions)
;;; the rest of your code for this file follows unchanged
;;; in file src/apprunner/functions.clj
(ns apprunner.functions
(:use clojure.contrib.duck-streams))
;;; the rest of your code for this file follows unchanged
Running the above at the REPL ((use 'apprunner.core)
etc.) works fine for me.
To summarise what was the problem here: Namespace names should contain dots where paths to files definining them contain slashes / backslashes (not that I mean relative paths -- relative to some directory which is actually on the classpath). Also, the src/
directory is the one you put in your classpath, so you don't include a src.
part in your namespace names. See e.g. the src/foo/bar/baz.clj
vs. foo.bar.baz
example in my answer to your earlier question.
Oh, and by the way, figuring out the classpath is difficult, period. So, be sure not to let yourself be discouraged by issues of this sort! :-) You might want to include info on how you run your code if you've got more namespace or classpath-related questions or if the above doesn't solve the problem for you, though.
精彩评论