2014-09-13 2 views
1

Я пытаюсь сделать функцию clojure, которая возвращает файлы в каталоге, который изменился сегодня. Это часть функциональности => дайте мне все файлы, которые были изменены сегодня, прокрутите файлы и найдите конкретное значение. Перечислите как файл, так и строку со значением.Функция clojure для возврата файлов в каталог

Я получил парсинг + листинг строк/файлов, а также «измененные файлы», однако я изо всех сил пытаюсь объединить эти два.

Функция я разработал так далеко, чтобы найти измененные файлы является:

(defn returnfilelist 
"returns all the files changed today in a directory" 
[d] 
(def dir (io/file d)) 
    (def files (for [file (file-seq dir) :when (= (datetostr (Date.(.lastModified file))) (datetostr (new Date))) ](str file ))) 
(doseq [f files] (println f))) ;; <==== this indeed shows the files changed today... 

Я создал функцию datetostr сделать фактическое сравнение по датам:

(defn datetostr [date] 
(str (.format (java.text.SimpleDateFormat. "yyyyMMdd")(.getTime date)))) 

Эта функция действительно перечисляет все файлы были изменены сегодня. Что я хотел бы сделать сейчас передать «файлы» в функции как:

(defn readdir [d] 
(ff/returnfilelist d)) ;; more to add... 

для дальнейшей обработки.

Я был бы признателен за помощь в этом вопросе, я, вероятно, наблюдаю за чем-то простым, но он продолжал меня прослушивать пару часов. Я искал в документации clojure и в Интернете, но я не понял правильное выражение поиска, чтобы получить ответ.

Направление достаточно, мне нравится учиться, и я довольно новичок в программировании clojure.

ответ

0

Чтобы получить значение, возвращаемое функцией, оно должно быть создано последним оператором, выполненным внутри. В вашем случае вы ничего не возвращаете, но определяете новые значения в глобальной области (что само по себе плохо); Вы должны использовать let для локальных значений:

(defn files-modified-today 
    [path] 
    (let [dir (io/file dir)] 
    (filter modified-today? (file-seq dir)))) 

(. Реализовать modified-today? по своему вкусу, например, как вы делали в ваш вопрос, используя datetostr)

Поскольку for форма последнее утверждение выполняется в функции его результат будет использоваться в качестве возвращаемого значения функции и может быть использован из других:

(defn read-dir 
    [path] 
    (for [f (files-modified-today path)] 
    (let [result (parse-file f)] 
     [f result])))) 

Это будет возвращать SEQ пара, содержащий согласованный файл в качестве первого элемента и го e результат parse-file (что бы это ни было) как второй.

Надеюсь, я не пропустил ваш вопрос полностью.

0

Ваш вопрос немного расплывчатый. Кроме того, кажется, что код, который вы пишете, далек от идиоматического. Я переписал некоторые из ваших функций ниже, чтобы представить вам некоторые общие идиомы clojure.

(import 'java.util.Date) 

(defn date->str [date] 
    (-> (java.text.SimpleDateFormat. "yyyyMMdd")    ;thread-first macro 
     (.format (.getTime date)) 
     str)) 

(defn todays-files [dir] 
    "returns all the files changed today in a directory" 
    (let [today (new Date)]         ;let bindings 
    (->> (file-seq (clojure.java.io/file dir))    ;thread-last macro. 
     (filter #(= (date->str (Date. (.lastModified %))) (date->str today))) 
     (map str)))) 

пронизывающих макросы (токарно-первая и последняя нить,) используются для создания трубопроводов, где выполняется одно преобразование данных, а затем переходит к следующему шагу.

Пусть привязки должны использоваться вместо defs внутри функций.

имена функций должны иметь тире, где обычно находятся пробелы. Также часто используется -> для функций преобразования. Например, date-to-str становится date-> str.

1

Пара вещей:

  1. returnfilelist использует def внутри функции. def определяет и связывает символы в глобальном пространстве имен пакета, что почти никогда не является тем, что вы хотите сделать. Вместо этого используйте let для привязки функции-локального символа.
  2. returnfilelist никогда не возвращает то, что он рассчитал. Последнее утверждение в функции, включающее дозу, фактически возвращает нуль. Возможно, вы захотите вернуть файлы.

Вот returnfilelist с соответствующими изменениями (я сохранил его как можно ближе к первоначальной реализации, как это возможно, чтобы проиллюстрировать ключевые изменения, чтобы получить код работу: другие ответы, используя filter более идиоматические, и должны быть предпочтительно):

(defn returnfilelist 
    "returns all the files changed today in a directory" 
    [d] 
    (let [dir (io/file d) 
     files (for [file (file-seq dir) 
        :when (= (datetostr (Date.(.lastModified file))) 
          (datetostr (new Date)))] 
       (str file))] 
    (doseq [f files] (println f)) ;; leaving this in for debugging 
    files)) ;; <--- the actual return value 

... и READDIR становится:

(defn readdir [d] 
    (let [todays-files (ff/returnfilelist d)] 
    ;; more to add... 
)) 
+0

Спасибо YosemiteMark за ответ. Я не знал, как вернуть стоимость и использовать ее. Так как все три человека сделали один и тот же комментарий о let, filter и idiom, мне нужно больше поработать над этим. Сначала я буду понимать ваш код, чтобы понять, что пошло не так в моем коде, после чего я рассмотрю два других, чтобы узнать больше о структуре языка clojure. – Jos