Я читаю о том, как ленивые последовательности могут вызывать OutOfMemoryError при использовании, скажем, цикла/повтора на больших последовательностях. Я пытаюсь загрузить 3MB-файл из памяти, чтобы обработать его, и я думаю, что это происходит со мной. Но я не знаю, есть ли идиоматический способ исправить это. Я попытался вставить doall's, но тогда моя программа, похоже, не закончилась. Малые входы работают: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)
Как я уже говорил выше, когда я вставлял команды в кучу мест, он, похоже, не заканчивался. Как я могу заставить это работать для больших файлов, и есть ли способ избавиться от когнитивной нагрузки на то, что мне нужно делать? Некоторые правила?
Обратите внимание, что мне нужно в конечном счете прочитать байты, а не символы. Или, скорее, я в конечном счете пытаюсь получить подписанный номер из каждых 16 бит. Я собирался взять эти пары и превратить их в отдельные числа во время моего следующего прохода с картой. Вероятно, есть лучший способ сделать это ... – MarkL4
Вот подробное обсуждение, которое может иметь значение: (http://programming-puzzler.blogspot.com/2009/01/laziness-in-clojure-traps-workarounds.html) – MarkL4
Как уменьшить когнитивную нагрузку - попробуйте написать как можно меньше своего собственного кода, используя обширные встроенные модули Clojure и библиотеку. 'group-by-twos' действительно большой, но на самом деле это не так.Также '(if (= (count a-list) 2) true false)' является верным способом сказать '(= (count a-list) 2)'. –