Prev: Evaluating/compiling forms in the current lexical environment.
Next: When are clojures more advantageous than CLOS?
From: Frode V. Fjeld on 3 Feb 2010 03:49 tar(a)sevak.isi.edu (Thomas A. Russ) writes: > (defun f(l) > (cond ((null l) nil) > ((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))) Doesn't this break if the list contains a NIL element? I guess the cadr should be a cdr. This is of course a very subjective issue, but I'm surprised that apparently so many programmers find it attractive to write trivial iterations in so many .. well, strange ways. I think the loop example I gave before is pretty much superior to all the other examples provided in this thread in the sense that it's easy to see what it does (correctly), and it's easy to see that it has perfect O(N) behavior both in terms of the number of list elements, the string lengths, and number of consecutive strings: (defun f (list) (loop while list collect (if (not (stringp (car list))) (pop list) (with-output-to-string (s) (loop while list while (stringp (car list)) do (write-string (pop list) s)))))) -- Frode V. Fjeld
From: Adam White on 3 Feb 2010 06:11 On 02/03/2010 09:27 AM, Tayssir John Gabbour wrote: [snippity doo dah] > Maybe the original poster is writing a tokenizer, and nil > represents some kinda null object. Actually there aren't supposed to be any '()s in the input stream. There are only supposed to be sublists representing actors (nominative, accusative, dative, genitive, verbs), four value tuples representing RGBA colours, and strings for verbatim text. The intended purpose is an english-grammar state machine. Given a list of strings and other items in a list, the state machine turns tokens into an english string. The adjacent string concatenation is just an optimisation hack for rendering. A
From: Pillsy on 3 Feb 2010 10:11 On Feb 3, 3:49 am, "Frode V. Fjeld" <fr...(a)netfonds.no> wrote: > t...(a)sevak.isi.edu (Thomas A. Russ) writes: > > > (defun f(l) > > (cond ((null l) nil) > > ((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))) > > Doesn't this break if the list contains a NIL element? I guess the cadr > should be a cdr. > > This is of course a very subjective issue, but I'm surprised that > apparently so many programmers find it attractive to write trivial > iterations in so many .. well, strange ways. I find it surprising too, and it's especially surprising that no one's used the one alternative strategy that would, IMO, actually have comparable clarity, which is to use *two* mutually recursing functions. The problem can be easily handled by a simple finite state machine, and mutually recursing functions are a good, obvious way to implement finite state machines. Put them inside a LABELS form and you can use Kaz's TAILPROG macro if your implementation won't merge the tail calls for some reason. > I think the loop example I > gave before is pretty much superior to all the other examples provided > in this thread in the sense that it's easy to see what it does > (correctly), and it's easy to see that it has perfect O(N) behavior both > in terms of the number of list elements, the string lengths, and number > of consecutive strings: > > (defun f (list) > (loop while list > collect (if (not (stringp (car list))) > (pop list) > (with-output-to-string (s) > (loop while list > while (stringp (car list)) > do (write-string (pop list) s)))))) I agree. I also think it's better than the obvious mutually recursing solution, but the disparity isn't as glaring. (defun merge-strings (list) (labels ((normal (list acc) (if (null list) (nreverse acc) (destructuring-bind (f . r) list (if (stringp f) (string-run r acc (list f)) (normal r (cons f acc)))))) (string-run (list acc sacc) (let ((f (first list))) (if (stringp f) (string-run (rest list) acc (cons f sacc)) (normal list (cons (apply #'concatenate 'string (nreverse sacc)) acc)))))) (normal list '()))) It would even work in Scheme, unlike the alleged Scheme solution posted in the thread, though you might have to write the moral equivalent of CONCATENATE for strings yourself. Cheers, Pillsy
From: André Thieme on 6 Feb 2010 07:51 Am 29.01.2010 19:23, schrieb W. James: > 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"] OMG, is Ruby really that complicated? William, you should try it in Lisp: (mapcat #(if (string? (first %)) [(apply str %)] %) (partition-by string? ["1" "2" 3 4 "5" "6" 7 8 "9"])) André -- Lisp is not dead. It's just the URL that has changed: http://clojure.org/
From: Wade on 6 Feb 2010 11:34 On Jan 29, 7:56 am, Adam White <spud...(a)iinet.net.au> wrote: > 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") > Saturday is play day... (defun concatas (list &aux result) (dolist (element list (nreverse result)) (if (and (stringp element) (stringp (car result))) (setf (car result) (concatenate 'string (car result) element)) (push element result)))) CL-USER> (concatas '("1" "2" 3 4 "5" "6" 7 8 "9")) ("12" 3 4 "56" 7 8 "9") CL-USER> Wade
First
|
Prev
|
Pages: 1 2 3 4 5 6 7 Prev: Evaluating/compiling forms in the current lexical environment. Next: When are clojures more advantageous than CLOS? |