2014-10-12 1 views
1

Я написал функцию, которая принимает каталог как входной файл и возвращает список файлов.clojure - conj, кажется, не добавляет значения в вектор

(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) 

Единственное, что здесь не работает, - это вызов вызова.

Вот мой тест

(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)))) 

Этот тест не удается, и показывает, что возвращаемое значение getFiles пусто.

+3

'conj' возвращает новый вектор с элементом добавленной в конце. Вы создаете вектор и отбрасываете его. – Lee

+0

спасибо. SO решение: (def names (conj names (. X toString))) – Luke

+0

Это будет работать, но это не идиоматический Clojure. См. Мой ответ. –

ответ

4

names - неизменный вектор. (conj names (. x toString)) создает новый вектор, но ничего не делает с ним. Другие проблемы с кодом:

  • Вы не хотите использовать doseq. Это для побочных эффектов, таких как печать вещей. Если вы создаете коллекцию, вам обычно не нужно выполнять итерацию в clojure, или если вы ее используете, вы можете использовать неизменный накопитель, цикл и повтор.
  • Вы не хотите использовать вложенные defs. Вы определяете глобальные переменные, и то, что вы хотите, - это локальные функции. Вместо этого используйте let.
  • Стиль именования clojure - использовать тире вместо случая верблюда (незначительный, просто конвенция).
  • Вы, кажется, не используете java.io importa в этом коде.
  • use В целом это не очень хорошая идея, если вы не ограничите ее несколькими явно названными функциями с помощью :only. Это делается для того, чтобы избежать путаницы, если вы посмотрите на неквалифицированное имя в своем коде, потому что вы не знаете, откуда оно взялось.

Вы хотите что-то вроде этого:

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

Я новичок в clojure, и это очень полезно. Спасибо – Luke

Смежные вопросы