clojure中的初学者:标记不同字符的列表

时间:2015-11-16 08:31:52

标签: regex clojure tokenize

所以我知道这不是解决这个问题的最佳方法,但我试图通过输入文件中的行列表,最终成为表达式。我有一个表达式列表,由于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)))

正如你可能会说的那样,我对函数式编程很陌生,所以欢迎任何建议!

1 个答案:

答案 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)。在命令式的世界中,我们习惯于运行几个“对数据进行压缩”的过程 - 在功能世界中,您经常将多个函数组合在一起以执行所有操作,然后运行结果。