Recursion 不在尾部位置复发
如何使用类似于Recursion 不在尾部位置复发,recursion,clojure,functional-programming,lisp,tail-recursion,Recursion,Clojure,Functional Programming,Lisp,Tail Recursion,如何使用类似于重复出现的不在尾部位置? 看看我的代码: (defn-main[&args] (println“嗨!键入文件名…”) (defn readFile[]) (让[文件名(读取行)] (让[rdr(读卡器文件名)] (如果不存在(.rdr) ((println“抱歉,此文件不存在。请键入有效的文件名…”) (再次出现) (定义列表'()) (doseq[行(行顺序rdr)] (如果不是(“)行) (concat列表(行))) (名单) (defn fileLinesList(readF
重复出现的不在尾部位置?
看看我的代码:
(defn-main[&args]
(println“嗨!键入文件名…”)
(defn readFile[])
(让[文件名(读取行)]
(让[rdr(读卡器文件名)]
(如果不存在(.rdr)
((println“抱歉,此文件不存在。请键入有效的文件名…”)
(再次出现)
(定义列表'())
(doseq[行(行顺序rdr)]
(如果不是(“)行)
(concat列表(行)))
(名单)
(defn fileLinesList(readFile))
...
...)
我知道我不能在这里使用recur
。。。但我都不知道我怎样才能在clojure做到
我是Clojure的新手,来自OOP环境。所以
在这种情况下有没有使用递归的方法?
什么是替代方案?首先,您不应该将函数定义嵌套在另一个
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))
如果
和如果不
要求其分支使用单个表达式,则
和否则
分支。如果要有多个表达式,需要将它们嵌套在do
:
(do
(println "Sorry, this file doesn't exists. Type a valid file name...")
(recur))
如果您需要If
或If not
而不使用else分支,则可以在时使用或非
时使用宏。然后,您不需要包装多个表达式,因为when
/when not
将为您的do
内部包装它们
(when true
(println 1)
(println 2))
相当于
(if true
(do
(println 1)
(println 2)))
首先,您不应该将函数定义嵌套在另一个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))
如果
和如果不
要求其分支使用单个表达式,则
和否则
分支。如果要有多个表达式,需要将它们嵌套在do
:
(do
(println "Sorry, this file doesn't exists. Type a valid file name...")
(recur))
如果您需要If
或If not
而不使用else分支,则可以在时使用或非
时使用宏。然后,您不需要包装多个表达式,因为when
/when not
将为您的do
内部包装它们
(when true
(println 1)
(println 2))
相当于
(if true
(do
(println 1)
(println 2)))
您的目标是编写一个从文件或现有函数读取文本行的函数吗?虽然您没有这样编写函数,但函数的逻辑似乎是“if-then-else”,在这种情况下,函数是尾部递归的。所以我建议这样重写它。还有其他一些Piotrek没有提到的错误,但是他的代码避免了这些错误。为了让您从正确的方向开始:(1)在Clojure中,日常常用函数都不会像您的行(concat list'(line))
那样修改数据,因为它位于doseq
内部<代码>目录
无法修改列表
;相反,它返回一个新的数据段,这是其参数的串联。(2)(行)
将返回一个包含单个元素的列表,即符号行
,但您需要的是该符号的内容。应该存在的内容是没有括号或引号的行
。(3)最后一行中的(list)
返回的内容是在没有参数的情况下调用函数list
,返回空列表的结果。当有一个不带引号的列表时,它的第一个参数通常被视为一个函数的名称,该函数将与列表中的其他元素一起作为它的参数进行计算(特殊情况下除外,如列表带引号时)。但是,在本例中,您重新定义了列表
,因此它不再引用函数。因此(list)
将产生错误,而不是执行list
通常命名的函数。您的目标是编写一个函数,从文件或现有函数中读取文本行,这对您来说足够了吗?虽然您没有这样编写,但函数的逻辑似乎是“if then else”,在这种情况下,函数是尾部递归的。所以我建议这样重写它。还有其他一些Piotrek没有提到的错误,但是他的代码避免了这些错误。为了让您从正确的方向开始:(1)在Clojure中,没有任何日常常用的函数会实际修改一段数据,因为您的行(concat list'(行)