Hi, The problem is that you end up with the front of your worklist being wrapped in <n-lines> nested calls to lazy-seq, one per each call to concat. Then, realizing the first element causes a stack overflow. This wouldn't happen if you reversed the arguments to concat, but then you wouldn't get what you want. Some possibilities (untested):
; probably the shortest, most idiomatic solution? (defn getstrlist [file] (apply concat (take-while identity (repeatedly #(getline file))))) ;or, using vectors, and written more like your solution: (defn getstrlist [file] (loop [worklst []] (if-let [x (getline file)] (recur (into worklst x)) worklst))) Cheers, Jason On Mar 1, 4:53 pm, Zededarian <zededar...@gmail.com> wrote: > My ultimate goal is to get a list of all the words in a file in > order. I have a function that will get a list of all the words on one > line of this file in order, and I want to efficiently concatenate > these lists to end up with one large list. I'm working with about > 12000 lines right now, but in a perfect world I'd like to scale much > higher. > > I started off just using concat. Basically my code looks like: > (defn getstrlist > ([file] > (loop [x (getline file) worklst '()] > (if x > (recur (getline file) (concat worklst (splitstr x))) > worklst)))) > > Then in the REPL, if I type (def a (getstrlist FILE)), it works fine. > But if I try to output a or take (first a), I get a stack overflow > error. I don't know why this is. I remember hearing somewhere that > Clojure had lazy sequences, so my best guess is that it isn't actually > concatenating anything, but is storing pointers to the start of all > the lists on a stack that overflows when I try to evaluate one of > these pointers. > > I know in Scheme I would write this using metalists that keep track of > the location of their last element: > (define (concat metalst1 metalst2) > (set-cdr! (car metalst1) (cdr metalst2)) > (set-car! metalst1 (car metalst2)) > metalst1) > > (define (make-metalst lst) > (cons (get-end lst) lst)) > > (define (get-end lst) > (if (null? lst) > '() > (if (null? (cdr lst)) > lst > (get-end (cdr lst))))) > > Which would be fairly efficient. But since Clojure doesn't seem to > have real lists, I'm not quite sure how I could port this over. I > suppose I could implement my own cons pairs like an idiot and do all > of this manually, but I figure I'm just not understanding the "Clojure > solution" to this problem. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---