我正在閱讀關於如何在大序列上使用循環/循環時惰性序列如何導致OutOfMemoryError的問題。我試圖從內存中加載一個3MB的文件來處理它,我認爲這發生在我身上。但是,我不知道是否有一種慣用的方法來解決它。我試圖把doall的,但我的程序似乎並沒有終止。小輸入工作:Clojure OutOfMemoryError
小輸入(文件的內容):AAABBBCCC 正確的輸出:((65 65)(65 66)(66 66)(67 67)(67 67))
代碼:
(def file-path "/Users/me/Desktop/temp/bob.txt")
;(def file-path "/Users/me/Downloads/3MB_song.m4a")
(def group-by-twos
(fn [a-list]
(let [first-two (fn [a-list] (list (take 2 a-list)))
the-rest-after-two (fn [a-list] (rest (rest a-list)))
only-two-left? (fn [a-list] (if (= (count a-list) 2) true false))]
(loop [result '() rest-of-list a-list]
(if (nil? rest-of-list)
result
(if (only-two-left? rest-of-list)
(concat result (list rest-of-list))
(recur (concat result (first-two rest-of-list))
(the-rest-after-two rest-of-list))))))))
(def get-the-file
(fn [file-name-and-path]
(let [the-file-pointer
(new java.io.RandomAccessFile (new java.io.File file-name-and-path) "r")
intermediate-array (byte-array (.length the-file-pointer))] ;reserve space for final length
(.readFully the-file-pointer intermediate-array)
(group-by-twos (seq intermediate-array)))))
(get-the-file file-path)
正如我上面所說的,當我在一堆地方放入doall時,它似乎沒有完成。我如何才能讓它運行大型文件,並且有辦法擺脫我需要做的任何事情的認知負擔?一些規則?
請注意,我確實需要最終讀取字節而不是字符。或者,相反,我最終試圖從每16位中得到一個有符號的數字。在我的下一次地圖傳球中,我打算將這些雙轉成單數。有可能有更好的方法來做到這一點... – MarkL4
這是一個可能相關的徹底討論:(http://programming-puzzler.blogspot.com/2009/01/laziness-in-clojure-traps-workarounds.html) – MarkL4
至於如何減少認知負擔 - 儘量使用Clojure廣泛的內置函數和庫來儘可能少地編寫自己的代碼。 「一羣一羣」真的很大,但它並沒有那麼重要。另外'(if(=(count a-list)2)true false)'是一種詳細的說法(=(count a-list)2)'。 –