plogan@mentor.com (Patrick Logan) (09/05/90)
I see a lot of LISP code building lists backwards and then reversing
them. I don't know if I've ever seen any C code doing that. Is it too
easy to write sloppy code in LISP? I don't think it is any more
difficult to write efficient list manipulations in Scheme than it is
in C.
Here is a procedure (in Scheme) that copies a list by adding items to
the end of a list and then returns that list. This isn't taught in the
Little LISPer, but it's not beyond the typical C programmer's
abilities.
(define (COPY-LIST lis)
(let ((header (cons #f '()))) ; Ignore the #f, build the list in the cdr.
(let loop ((tail header) (lis lis))
(if (null? lis)
(cdr header)
(begin (set-cdr! tail (cons (car lis) '()))
(loop (cdr tail) (cdr lis)))))))
Here is an "object" that responds to two messages. For the cost of
building a closure of a few words in size, it abstracts the code for
adding items to the end of a list.
Messages:
((object 'EXTEND!) item) ....... Add item to the end of the list.
(object 'LIST) ................. Return the list.
Scheme->C -- 23feb90jfb -- Copyright 1989 Digital Equipment Corporation
> (define (MAKE-TAIL-LIST)
(let* ((head (cons #f '())) ; Ignore the #f, use for tail-cons'ing.
(tail head))
(lambda (msg)
(case msg
((extend!)
(lambda (item)
(let ((new-tail (cons item '())))
(set-cdr! tail new-tail)
(set! tail new-tail))))
((list) (cdr head))))))
MAKE-TAIL-LIST
> (define a (make-tail-list))
A
> (a 'list)
()
> ((a 'extend!) 1)
(1)
> ((a 'extend!) 2)
(2)
> ((a 'extend!) 3)
(3)
> (a 'list)
(1 2 3)
--
Patrick Logan, uunet!mntgfx!plogan
Mentor Graphics Corp. 8500 SW Creekside, Beaverton, Oregon 97005-7191briscoe-duke@cs.yale.edu (Duke Briscoe) (09/06/90)
In article <1990Sep5.011910.1177@mentor.com> Patrick Logan writes: >I see a lot of LISP code building lists backwards and then reversing >them. I don't know if I've ever seen any C code doing that. Is it too >easy to write sloppy code in LISP? I don't think it is any more >difficult to write efficient list manipulations in Scheme than it is >in C. > I did some timings on compiled T code, and the difference between copying a list using your copy-list function and using a function (define (dcl lis) (reverse! (reverse lis))) was only 20%, the important thing being that this is an algorithmic difference of a small constant factor. The reverse functions in T are coded in T, not hand-coded assembly by the way. If the operations used to build the elements of the list are expensive (just copying the elements is the least expensive thing I can think of) then the reverse! step is going to make relatively less of a percentage difference. I think in many cases there isn't going to be much difference. If someone is using reverse instead of reverse! then that could be more serious because of the extra consing. I think the important thing is that the standard functions be coded efficiently, but for most user applications a person doesn't need to get involved with potentially tricky pointer manipulations. Duke