Prev: Evaluating/compiling forms in the current lexical environment.
Next: When are clojures more advantageous than CLOS?
From: Adam White on 29 Jan 2010 19:48 On 01/30/2010 03:06 AM, Richard Fateman wrote: > (defun f(l) > (cond ((and(stringp (car l))(stringp (cadr l))) > (f (cons (concatenate 'string (car l) (cadr l)) > (cddr l)))) > ((cadr l) (cons (car l)(f (cdr l)))) > (t l))) > > ;; (f '("1" "2" 3 4 "5" "6" 7 8 "9")) --> ("12" 3 4 "56" 7 8 "9") Thanks Richard - that's exactly the sort of thing I had in mind but couldn't express. A
From: Pillsy on 29 Jan 2010 20:02 On Jan 29, 4:15 pm, Kaz Kylheku <kkylh...(a)gmail.com> wrote: > Raymond Wiker wrote: > > "Frode V. Fjeld" <fr...(a)netfonds.no> writes: [...] > Users of CL (COBOL-LISP) would be helpless without loop. You mean helpless the same way you are, writing programs O(N^2) behavior due to repeatedly using string-append? > Scheme: > (define (fuse in out) > (if (null? in) (reverse out) > (let ((x (car in))) > (fuse (cdr in) > (if (and (string? x) (pair? out) (string? (car out))) > (cons (string-append (car out) x) (cdr out)) > (cons x out)))))) Sheesh, Pillsy
From: Huai Yuan on 30 Jan 2010 08:54 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))
From: Ole Arndt on 30 Jan 2010 10:00 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 ;) Ole -- Ole Arndt http://www.sugarshark.com
From: Tayssir John Gabbour on 30 Jan 2010 10:23
Hi, On Jan 29, 8:06 pm, Richard Fateman <fate...(a)cs.berkeley.edu> wrote: > (defun f(l) > (cond ((and(stringp (car l))(stringp (cadr l))) > (f (cons (concatenate 'string (car l) (cadr l)) > (cddr l)))) > ((cadr l) (cons (car l)(f (cdr l)))) > (t l))) If I understand correctly, there's a bug -- CADR will have a problem with nil. Instead, CDDR should be used, otherwise this happens: cl-user> (f '(1 nil "2" "3" "4" "5")) (1 NIL "2" "3" "4" "5") This computer I'm on don't have Slime+SBCL, so excuse me for the Clojure version -- this is trivially translatable to idiomatic CL: (defn vec-butlast [a-vector] (subvec a-vector 0 (max 0 (dec (count a-vector))))) (defn concatenate-adjacent-strings [lst] (reduce (fn [accumulator item] (if (and (string? (last accumulator)) (string? item)) (conj (into [] (vec-butlast accumulator)) (str (last accumulator) item)) (conj accumulator item))) [] lst)) People elsewhere on this thread are attempting to buffer the strings to avoid worst-case repeated string concatenation, so here's an optimized version: (defn concatenate-adjacent-strings-2 [lst] (let [[result buffer] (reduce (fn [[accumulator buffer] item] (cond (string? item) [accumulator (conj buffer item)] (seq buffer) [(conj accumulator (apply str buffer) item) []] :else [(conj accumulator item) buffer])) [[] []] lst) result (if (seq buffer) (conj result (apply str buffer)) result)] result)) While I'm a big LOOP partisan, I think REDUCE is just more streamlined, perhaps clearer than LOOP. I agree with Kaz that pattern- matching would be great, if there were an available library. All the best, Tayssir |