clojure - conj似乎没有为vector增加价值

时间:2014-10-12 16:12:48

标签: clojure

我编写了一个函数,它将一个目录作为输入并返回一个文件列表。

(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的返回值为空。

1 个答案:

答案 0 :(得分: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)))