Прежде всего, вы не должны определять свои функции в другом defn
(-main
в этом случае). defn
или def
всегда определяет привязки символов на верхнем уровне пространства имен, и они не вложены. Если вы хотите определить локальную область действия, вам необходимо использовать let
и fn
, например.
(let [my-fn (fn [a b] (+ a b))]
(my-fn 1 2))
В вашем конкретном случае я думаю, что было бы проще разделить свой код на несколько функций. Таким образом, он будет более читабельным.
Подсказка для имени файла - это одна часть вашей логики.
(defn get-existing-filename []
(let [filename (read-line)]
(if (.exists (java.io.File. filename))
filename
(do
(println "Sorry, this file doesn't exists. Type a valid file name...")
(recur)))))
Затем вы можете использовать его для чтения файла удаление пустых строк:
(with-open [input (clojure.java.io/reader (get-existing-filename))]
(->> (line-seq input)
(remove empty?)
(doall)))
Для файла с следующим содержанием:
AAA
BBB
CCC
DDD
вернет
("AAA" "BBB" "CCC" "DDD")
Если вы действительно этого хотите, Функция ля, следующая будет работать:
(defn read-file []
(let [filename (read-line)]
(if (.exists (java.io.File. filename))
(with-open [input (clojure.java.io/reader (get-existing-filename))]
(->> (line-seq input)
(remove empty?)
(doall)))
(do
(println "Sorry, this file doesn't exists. Type a valid file name...")
(recur)))))
Наконец, эта функция может быть вызвана из -main
.
Я также заметил, еще один вопрос, в примере кода:
((println "Sorry, this file doesn't exists. Type a valid file name...")
(recur))
if
и if-not
требуют одно выражение для их then
и else
ветвей. Если вы хотите иметь несколько выражений, вы должны вкладывать их в do
:
(do
(println "Sorry, this file doesn't exists. Type a valid file name...")
(recur))
Если вам нужно if
или if-not
без еще филиала, то вы можете использовать when
или when-not
макросы. Тогда вам не нужно обертывать несколько выражений, потому что when
/when-not
обернет их для вашей внутренней части do
.
(when true
(println 1)
(println 2))
эквивалентно
(if true
(do
(println 1)
(println 2)))
Ваша цель, чтобы написать функцию чтения строк текста из файла или существующей функции будет достаточно хорошо для вас? –
Ну ... Функция, которая возвращается, если файл существует уже существует. Я хочу вызвать функцию readFile до тех пор, пока не будет указано имя файла. –
Хотя вы этого не писали, логика вашей функции кажется «если <файл не существует», то else <делать вещи, предполагающие существование файла>>, и в этом случае функция * является хвостовой рекурсивной. Поэтому я предлагаю переписать его так. –
tfb