我是Clojure的新手,在如何避免某些情況下的堆疊溢位方面遇到了麻煩。在嘗試將一個決議專案移植到 Clojure 時,出現了這樣一種情況,我發現了一個名為kern的決議器組合庫。
Kern定義了一個 "多頭 "分析器的遞回實作。source
這對小的輸入來說是很好的:
這對小的輸入來說是很好的。
(def input-text "The blue {cat} and the red {dog} became best friends with the white {wolf}. END {不包括}")
(def between-brackets "抓取括號內所有文本的決議器")
(between (sym* {) (sym* }) (< > (many (none-of* "}"/span>)))))
(def parse-enclosed-words "決議器,嘗試抓取括號內的文本。
當它無法做到時跳過一個字符,并在遇到字串END時停止"。
(many-till (<|> (skip any-char)) (token* "END") )
(filter #(some? %) (value parse-enclosed-words input-text) ;; => ("貓" "狗" "狼")
不幸的是,隨著輸入字串的增長,決議器遇到了堆疊溢位:
(def file-input-text (slurp(io/resource "[input-text-20x-repeated. txt][2]") ))
(filter #(some? %) (value parse-enclosed-words file-input-text) ;; => Unhandled java.lang.StackOverflowError。
從我在網上看到的資訊來看,這可能是由于該函式使用了消耗堆疊的遞回。我玩了一些嘗試,使用 "遞回 "關鍵字重寫該函式,但由于遞回呼叫不在尾部位置,這似乎并不奏效。
如何修改many-till以避免堆疊溢位?
uj5u.com熱心網友回復:
我不認為你可以通過庫提供的抽象來做到這一點。這是一個非常自然的many-till的定義,在Parsec(Kern顯然是受其啟發的庫)中也能正常作業。但是Clojure沒有Haskell的懶惰評估和自動蹦床,所以many-till構建的嵌套lambdas不可避免地要消耗無界堆疊。你需要一個更像其many的實作,它通過手工從一個函式中構建一個決議器。我想在下面附上它的源代碼,但我并不擁有它,因此我認為我無權給 Stack Overflow 提供 CC BY-SA 4.0 許可,因為張貼它就可以了。相反,這里有一個指向其來源的鏈接。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/319283.html
標籤:
