From: vippstar on 9 Dec 2009 09:39 On Dec 9, 4:29 pm, "Frode V. Fjeld" <fr...(a)netfonds.no> wrote: > Rainer Joswig <jos...(a)lisp.de> writes: > > > CL-USER 2 > (let ((l1 (copy-tree '((a 1) (b 2) (c 3))))) > > (values (mapcan #'identity l1) > > [..] > > > COPY-LIST is not enough, since that copies only > > the first level cons cells. > > Shouldn't (mapcan #'copy-list l1) do the trick? Depends on what you'll do with that list afterwards. You might modify shared cons cells or the objects stored in CAR/CDR, which might have an unexpected effect. Originally the intent was to be used with macros, which don't do that. Example: (let ((x (cons 0 nil))) (setf (caar (mapcan #'copy-list (list (list x)))) 0) x) evaluates to (1). With #'copy-tree used, it would be (0).
From: Pascal Costanza on 9 Dec 2009 10:13 On 09/12/2009 15:22, Tamas K Papp wrote: > On Wed, 09 Dec 2009 15:15:54 +0100, Pascal Costanza wrote: > >> On 09/12/2009 14:53, Tamas K Papp wrote: >>> On Wed, 09 Dec 2009 04:10:20 -0800, vippstar wrote: >>> >>>> On Dec 9, 1:49 pm, Pascal Costanza<p...(a)p-cos.net> wrote: >>>>> On 09/12/2009 12:19, Tamas K Papp wrote: >>>>> >>>>>> Is there a more idiomatic way to implement this function: >>>>> >>>>>> (defun flatten1 (list) >>>>>> (apply #'concatenate 'list list)) >>>>> >>>>> (apply #'append lists) >>>>> (apply #'nconc lists) >>>>> (loop for list in lists append list) >>>>> (loop for list in lists nconc list) >>>> >>>> (mapcan #'identity list) >>> >>> Thanks! The original application was >>> >>> (setf ,@(flatten1 (mapcar ... >>> >>> so I guess that I can just use >>> >>> (setf ,@(mapcan ... >>> >>> and I don't even need flatten1 after all :-) >> >> Be careful: mapcan is a destructive operation, so you should also use it >> if you are sure that the lists are freshly created, and/or not used by >> any other part of the program. If you are not sure about it, it's better >> to use the LOOP/APPEND idiom, or look for mapappend, which you can >> sometimes find defined as a utility function. > > I am using backquote to construct the lists. > > The spec says that "The constructed copy of the template might or > might not share list structure with the template itself.", so I am > wondering. > > My examples look like this: > > (setf ,@(mapcan (lambda (size) `((mem-ref ,size :int32) -1)) sizes)) > > (setf ,@(mapcan (lambda (returned-size pointer lla-type size) > `(,returned-size (floor (mem-aref* ,pointer ,lla-type)) > (mem-ref ,size :int32) ,returned-size)) > returned-sizes pointers lla-types sizes)) > > I would reason that this is safe since all lists are constructed from > atoms, so they cannot share structure. > > But is (mapcan (lambda () `(...))) safe in general? To be honest, I don't know. I'm trying to ensure that I don't write overly inefficient code most of the time, but when it not obvious anymore whether something will be safe or not, it's likely that later readers will also not understand whether it's obvious or not what your code does. So when in doubt, I tend to use a simpler approach, that makes it obvious that bad things won't happen. The following is very obvious code for me, plus it won't be very inefficient, as far as I can tell. (setf ,@(loop for size in sizes append `((mem-ref ,size :int32) -1))) (setf ,@(loop for returned-size in returned-sizes for pointer in pointers for lla-type in lla-types for size in sizes append `(,returned-size (floor (mem-aref* ,pointer ,lla-type)) (mem-ref ,size :int32) ,returned-size))) Pascal -- My website: http://p-cos.net Common Lisp Document Repository: http://cdr.eurolisp.org Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Kaz Kylheku on 9 Dec 2009 16:10 On 2009-12-09, Tamas K Papp <tkpapp(a)gmail.com> wrote: > Is there a more idiomatic way to implement this function: > > (defun flatten1 (list) > (apply #'concatenate 'list list)) > Example: > > (flatten1 '((a 1) (b 2) (c 3))) ;; => (A 1 B 2 C 3) Your function works on a sequence of sequences, not just a list of lists. If you just want to be flattening a list of lists, then APPEND will do it: (apply #'append list-of-lists) But, either way, with APPLY, you may run into an argument passing limit, if the list-of-lists is large enough. Another idiom is REDUCE: decimate the list by repeatedly applying the function as a binary operation. (reduce #'append list-of-lists) This is nice as an expressive idiom, but contains an inefficiency. A left-associative append (i.e. adding :from-end t) will have to repeatedly keep walking the growing accumulated list to find the tail (unless the compiler recognizes this whole thing as an idiom). You can add :from-end t to make it right associative; but that has its costs too, namely finding the end of the list-of-lists, and using extra storage to be able to navigate backwards. > I am using it in macros, eg > > (setf ,(flatten1 (function-that-generates-pairs))) Never heard of the ,@ splicing operator? ;)
From: Pillsy on 9 Dec 2009 16:59 On Dec 9, 9:22 am, Tamas K Papp <tkp...(a)gmail.com> wrote: [...] > The spec says that "The constructed copy of the template might or > might not share list structure with the template itself.", so I am > wondering. > My examples look like this: > (setf ,@(mapcan (lambda (size) `((mem-ref ,size :int32) -1)) sizes)) > (setf ,@(mapcan (lambda (returned-size pointer lla-type size) > `(,returned-size (floor (mem-aref* ,pointer ,lla-type)) > (mem-ref ,size :int32) ,returned-size)) > returned-sizes pointers lla-types sizes)) In this particular case, I'd advocate using `(progn ,@(mapcar (lambda (size) `(setf (mem-ref ,size :int32) -1)) sizes)) `(progn ,@(mapcar (lambda (returned-size pointer lla-type size) `(setf ,returned-size (floor (mem-aref* ,pointer ,lla- type)) (mem-ref ,size :int32) ,returned-size))) returned-sizes pointers lla-types sizes)) This nicely eliminates all questions of whether some interaction between shared list structure and destructive operations will blow up in your face and gets the job done just as well. Cheers, Pillsy
From: w_a_x_man on 10 Dec 2009 02:03 On Dec 9, 5:19 am, Tamas K Papp <tkp...(a)gmail.com> wrote: > Is there a more idiomatic way to implement this function: > > (defun flatten1 (list) > (apply #'concatenate 'list list)) > > Example: > > (flatten1 '((a 1) (b 2) (c 3))) ;; => (A 1 B 2 C 3) > > I am using it in macros, eg > > (setf ,(flatten1 (function-that-generates-pairs))) > > Thanks, irb(main):001:0> [%w(a 1), %w(b 2), %w(c 3)].flatten => ["a", "1", "b", "2", "c", "3"]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: complex symmetric matrices Next: Parallel programming in CL? |