0

I am new to clojure. I am trying to write a program which reads data from a file (comma seperated file) after reading the data I am trying to split each line while delimiter "," but I am facing the below error:

CompilerException java.lang.NullPointerException, compiling:(com\clojure\apps\StudentRanks.clj:26:5)

Here is my code:

(ns com.clojure.apps.StudentRanks)
(require '[clojure.string :as str])

 (defn student []
  (def dataset (atom []))
  (def myList (atom ()))
  (def studObj (atom ()))
   (with-open [rdr (clojure.java.io/reader "e:\\example.txt")]
    (swap! dataset into (reduce conj [] (line-seq rdr)))
   )
  (println @dataset)
  (def studentCount (count @dataset))
  (def ind (atom 0))
  (loop [n studentCount]
  (when (>= n 0)
   (swap! myList conj (get @dataset n))
   (println (get @dataset n))
   (recur (dec n))))
  (println myList)
  (def scount (count @dataset))
  (loop [m scount]
 (when (>= m 0)
   (def data(get @dataset m))
   (println (str/split data #","))
   (recur (dec m))))
  )
(student)

Thanks in advance.

3
  • 1
    Don't use def within functions, use let. Commented Jan 22, 2019 at 14:05
  • 1
    My suggestion is to slow down a bit. Being new to clojure you probably want to consider atoms, swap! and even loops as more advanced topics. You don't need any of those things to read lines from a file and split them. In fact you rarely need them, even in quite complex programs :-) Commented Jan 22, 2019 at 14:44
  • my requirement is read file content line by line and push each line into a list. for ex: my file content is "1,bharath,85,86,89,85" and requirement is: [(1 bharath 85 86 89 85)]. Commented Jan 22, 2019 at 15:17

2 Answers 2

1

As pointed out in the comments, the first problem is that you are not writing correct Clojure. To start, def should never be nested -- it's not going to behave like you hope. Use let to introduce local variables (usually just called locals because it's weird to call variables things that don't vary). Second, block-like constructs (such as do, let or with-open evaluates to the value of their last expression.

So this snippet

(def dataset (atom []))
(with-open [rdr (clojure.java.io/reader "e:\\example.txt")]
  (swap! dataset into (reduce conj [] (line-seq rdr))))

should be written

(let [dataset
      (with-open [rdr (clojure.java.io/reader "e:\\example.txt")]
        (into [] (line-seq rdr)))]
  ; code using dataset goes here
)

Then you try to convert dataset (a vector) to a list (myList) by traversing it backwards and consing on the list under construction. It's not needed. You can get a sequence (list-like) out of a vector by just calling seq on it. (Or rseq if you want the list to be reversed.)

Last, you iterate once again to split and print each item held in dataset. Explicit iteration with indices is pretty unusual in Clojure, prefer reduce, doseq, into etc.

Here are two ways to write student:

(defn student [] ; just for print
  (with-open [rdr (clojure.java.io/reader "e:\\example.txt")]
    (doseq [data (line-seq rdr)]
      (println (str/split data #",")))))

(defn student [] ; to return a value
  (with-open [rdr (clojure.java.io/reader "e:\\example.txt")]
    (into []
      (for [data (line-seq rdr)]
        (str/split data #",")))))

I hope this will help you to better get Clojure.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks a lot cgrand. now i understood it better.
0

I suggest you use a csv library:

(require '[clojure.data.csv :as csv])
(csv/read-csv (slurp "example.txt"))

Unless this is some file io exercise.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.