Prev: Evaluating/compiling forms in the current lexical environment.
Next: When are clojures more advantageous than CLOS?
From: Tayssir John Gabbour on 30 Jan 2010 11:26 On Jan 30, 4:23 pm, Tayssir John Gabbour <tayssir.j...(a)googlemail.com> wrote: > While I'm a big LOOP partisan, I think REDUCE is just more > streamlined, perhaps clearer than LOOP. Hmm, I take that back; some of the ones where you're modifying lists while iterating over them are pretty concise and clear. All the best, Tayssir
From: Raymond Wiker on 30 Jan 2010 12:05 Huai Yuan <huaiyuan(a)gmail.com> writes: > Adam White <spudboy(a)iinet.net.au> writes: >> Given a mixed list of strings and other items, I'd like to concatenate >> all strings (and only strings) adjacent to each other. >> >> So for '("1" "2" 3 4 "5" "6" 7 8 "9"), we should return >> >> ("12" 3 4 "56" 7 8 "9") > [...] > > (defun concatenate-adjacent-strings (list) > (reduce (lambda (x y) > (if (and (stringp x) (stringp (car y))) > (cons (concatenate 'string x (car y)) (cdr y)) > (cons x y))) > list :from-end t :initial-value nil)) I wish I'd been able to think up something like this :-)
From: Tayssir John Gabbour on 30 Jan 2010 12:43 On Jan 30, 5:26 pm, Tayssir John Gabbour <tayssir.j...(a)googlemail.com> wrote: > > While I'm a big LOOP partisan, I think REDUCE is just more > > streamlined, perhaps clearer than LOOP. > > Hmm, I take that back; some of the ones where you're modifying lists > while iterating over them are pretty concise and clear. Bothered that the LOOP versions are shorter than the relative monstrosity I created, I looked for more impressive higher-order function stuff to cut down on size: (defn concatenate-adjacent-strings [lst] (lazy-seq (cond (empty? lst) nil (string? (first lst)) (let [[strings remainder] (split-with string? lst)] (cons (apply str strings) (concatenate-adjacent-strings remainder))) :else (cons (first lst) (concatenate-adjacent-strings (rest lst)))))) Ssomeone more familiar with lazy eval than me can probably translate this into idiomatic CL, and compare it to the succinct LOOP versions. All the best, Tayssir
From: Kaz Kylheku on 30 Jan 2010 14:19 On 2010-01-30, Ole Arndt <ole(a)sugarshark.com> wrote: > Richard Fateman <fateman(a)cs.berkeley.edu> writes: > >> (defun f(lis) >> (let ((h (first lis))(r (rest lis))) >> (cond ((and(stringp h)(stringp (first r))) >> (f (cons (concatenate 'string h (first r)) >> (rest r)))) >> (r (cons h (f r))) >> (t lis)))) > > Much nicer, but not tail recursive anymore ;) Don't forget that we can rewrite tail recursion into proper iteration with a macro, which preserves the tail recursive expression. Search the archives for the TAILPROG macro.
From: W. James on 2 Feb 2010 03:11
W. James wrote: > Ole Arndt wrote: > > > Adam White <spudboy(a)iinet.net.au> writes: > > > > > Given a mixed list of strings and other items, I'd like to > > > concatenate all strings (and only strings) adjacent to each other. > > > > > > So for '("1" "2" 3 4 "5" "6" 7 8 "9"), we should return > > > > > > ("12" 3 4 "56" 7 8 "9") > > > > > > My first solution which works, but is as ugly as sin is: > > > > > > (loop > > > with curr = "" > > > with save = '() > > > for p in '("1" "2" 3 4 "5" "6" 7 8 "9") do > > > (cond > > > ((stringp p) (setf curr (concatenate 'string curr p))) > > > ((equal curr "") (push p save)) > > > (t (push curr save) (push p save) (setf curr ""))) > > > finally (return (nreverse (cons curr save)))) > > > > > > Surely there has got to be a better way to do this! > > > > > > Any pointers? > > > > And another solution: > > > > (defun merge-strings (list) > > (labels ((conc (beg cur rest) > > (cond ((null cur) > > beg) > > ((and (stringp cur) (stringp (first rest))) > > (conc beg > > (concatenate 'string cur (first rest)) > > (rest rest))) > > (t > > (conc (nconc beg (list cur)) > > (first rest) > > (rest rest)))))) > > (conc nil (first list) (rest list)))) > > CL (COBOL-LISP) isn't very good at handling lists. You've illustrated > that very well. > Let's use Matzlisp: > > ["1","2",3,4,"5","6",7,8,"9"].inject([]){|a,x| > (if x.is_a?(String) and a.last.is_a?(String) > a.last > else > a > end) << x > a > } > ==>["12", 3, 4, "56", 7, 8, "9"] A little golfing: ["1","2",3,4,"5","6",7,8,"9"].reduce([]){|a,x| (x.is_a?(String) && a[-1].is_a?(String) ? a[-1] : a ) << x a} ==>["12", 3, 4, "56", 7, 8, "9"] -- |