所以我知道这不是解决这个问题的最佳方法,但我试图通过输入文件中的行列表,最终成为表达式。我有一个表达式列表,由于split-the-list函数,每个表达式都有自己的列表。我的下一步是用id
替换字符,用int
整理字符,用addop
替换+或 - 。我有正则表达式来查找我的符号是否与这些符号相匹配,但是当我尝试替换它们时,我只能得到最后一个for循环,我打电话给我留下任何持久的结果。我知道它归结为函数式编程的工作方式,但是我无法绕过这个程序的轨迹,以及如何替换每个单独的输入类型并将结果保存在一个列表中。
(def reint #"\d++")
(def reid #"[a-zA-Z]+")
(def readdop #"\+|\-")
(def lines (into () (into () (clojure.string/split-lines (slurp "input.txt")) )))
(defn split-the-line [line] (clojure.string/split line #" " ))
(defn split-the-list [] (for [x (into [] lines)] (split-the-line x)))
(defn tokenize-the-line [line]
(for [x line] (clojure.string/replace x reid "id"))
(for [x line] (clojure.string/replace x reint "int"))
(for [x line] (clojure.string/replace x readdop "addop")))
(defn tokenize-the-list [] (for [x (into [] (split-the-list) )] (tokenize-the-line x)))
正如你可能会说的那样,我对函数式编程很陌生,所以欢迎任何建议!
答案 0 :(得分:2)
您正在使用do
块,它会评估多个表达式(通常用于副作用),然后返回最后一个。您无法看到它,因为fn
(因此defn
)隐式包含一个。就这样,行
(for [x line] (clojure.string/replace x reid "id"))
(for [x line] (clojure.string/replace x reint "int"))
被评估(分成两个不同的懒惰序列),然后扔掉。
为了使它们影响返回值,您必须捕获它们的返回值并在下一轮替换中使用它们。
在这种情况下,我认为构成替换的最自然方式是线程宏->
:
(for [x line]
(-> x
(clojure.string/replace reid "id")
(clojure.string/replace reint "int")
(clojure.string/replace readdop "addop")))
这创建了代码,reid
替换为x
作为第一个参数,然后reint
替换为第一个参数的结果,依此类推。
或者,您可以使用comp
撰写匿名函数,例如(fn [s] (clojure.string/replace s reid "id")
(部分应用replace
)。在命令式的世界中,我们习惯于运行几个“对数据进行压缩”的过程 - 在功能世界中,您经常将多个函数组合在一起以执行所有操作,然后运行结果。