2012-05-18 198 views
3

我想了解如何更改在Clojure函数的let绑定中声明的变量的值。以下是我正在使用的代码。我希望函数返回java.lang.String对象,该对象包含String中包含的文本。是否可以修改let绑定?

(defn read-text-from-file 
    {:doc "fn read-text-from-file is used to output in \"string\" 
format the text in a file."} 
    [#^String file-name] 
    (let [buff-reader (open-file-reader file-name)] 
    (loop [full-text "" line (.readLine buff-reader)] 
    (when line 
     (-> full-text (.concat line)) 
;  (println full-text) 
     (recur (-> file-name (.concat line)) (.readLine buff-reader)))))) 

注意:函数'开放文件读者低于:

(defn open-file-reader 
    {:doc "This is used to open a file, ready for reading"} 
    [file-name] 
    (let [file-object (java.io.File. file-name) 
     buff-reader (-> file-object (java.io.FileReader.) 
         (java.io.BufferedReader.))] 
    buff-reader)) 
+2

哪一部分,你要完成的东西需要改变一个let绑定? –

回答

8

let的绑定是不可变的,不能反弹。即使您可以重新绑定它们,您的问题仍然存在于代码中的其他地方。您需要做的是使用if特殊窗体而不是when宏。使用if时,如果不是line is nullrecur,则可以返回full-text


虽然,我建议你检查一下slurp函数,它可以为你做这一切。

user=> (doc slurp) 
------------------------- 
clojure.core/slurp 
([f & opts]) 
    Opens a reader on f and reads all its contents, returning a string. 
    See clojure.java.io/reader for a complete list of supported arguments. 
nil 

如果仍然希望自己实现这个功能,我建议你至少要把full-text一个StringBuilder。然后,您可以通过说(str full-text)将它转换为字符串,当您最终返回时。然而,Maurice Reeves在his answer中提供了一个更习惯的Clojure解决方案。

4

让绑定,如函数参数,是不可变的,所以你不能改变它们的值。

3

你不能改变let的绑定。只是不可能。你试图完成的任务可以用其他人提到的slurp完成,但是如果你想要走的路线,可以使用line-seq和申请成为下方观察:

(defn fetch-file-text [file-name] 
    (with-open [rdr (clojure.java.io/reader file-name)] 
      (apply str (line-seq rdr)))) 

你可以阅读更多关于线-seq的位置:http://clojuredocs.org/clojure_core/clojure.core/line-seq

,更多的是应用在这里: http://clojuredocs.org/clojure_core/clojure.core/apply