Luke
Luke

Reputation: 1814

clojure - conj doesn't seem to add value to vector

I have written a function which takes a directory as input and returns a list of files.

(ns musicdb.filesystem)
(import '(java.io.File) '(java.net.url) '(java.io))
(use 'clojure.java.browse)
(require '[clojure.string :as str])

(defn getFiles
    "get a list of all files"
    [searchPath]
        (def directory (clojure.java.io/file searchPath))
        (def files (file-seq directory))
        (def fonly (filter (fn [x]
            (. x isFile)) files))
        (def names [])
        (doseq [x fonly] 
            (conj names (. x toString)) ;doesn't seem to work
            (println (. x toString))) ;but this DOES print the file path
        names)

The only thing that doesn't work here, is the conj call.

Here is my test

(ns musicdb.core-test
  (:require [clojure.test :refer :all]
            [musicdb.core :refer :all]
            [musicdb.filesystem :refer :all]))

(deftest test_0
  (testing "getFiles returns valid result"
    (is (> (count (getFiles "/home/ls/books/books")) 1))
    (doseq [i (take 5 (getFiles "/home/ls/books/books"))] (searchBook i))))

This test fails and shows that the return value of getFiles is empty.

Upvotes: 2

Views: 414

Answers (1)

Diego Basch
Diego Basch

Reputation: 13079

names is an immutable vector. (conj names (. x toString)) creates a new vector but doesn't do anything with it. There are other problems with your code:

  • you don't want to use doseq. It's for side effects, such as printing things out. If you're creating a collection you usually don't need to iterate in clojure, or if you do you can use an immutable accumulator, loop and recur.
  • You don't want to use nested defs. You're defining globals, and what you want are function locals. Use let instead.
  • The clojure naming style is to use dashes instead of camel case (minor, just a convention).
  • You don't seem to be using your java.io importa in this code.
  • use in general is not a good idea, unless you restrict it to a few explicitly named functions with :only. This is to avoid confusion when looking at an unqualified name in your code, because you wouldn't know where it came from.

You want something like this:

(defn get-files [search-path]
  (let [directory (clojure.java.io/file search-path)
        files (file-seq directory)
        fonly (filter #(.isFile %) files)]
   (map #(.toString %) fonly)))

Upvotes: 4

Related Questions