From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Pascal J. Bourguignon" Newsgroups: gmane.emacs.help Subject: Re: `append' vs. `nconc' Date: Thu, 31 Dec 2015 09:54:11 +0100 Organization: Informatimago Message-ID: <87mvsrc824.fsf@kuiper.lan.informatimago.com> References: <568164D8.6050700@ojkastl.de> <87io3iyr7t.fsf@debian.uxu> <87si2kezg1.fsf@mithlond.arda> <87a8osrlj4.fsf_-_@debian.uxu> <87lh8bgafa.fsf@mithlond.arda> <87r3i3ch63.fsf@kuiper.lan.informatimago.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: ger.gmane.org 1451552125 15490 80.91.229.3 (31 Dec 2015 08:55:25 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 31 Dec 2015 08:55:25 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Dec 31 09:55:22 2015 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1aEZ0y-0007yW-Qq for geh-help-gnu-emacs@m.gmane.org; Thu, 31 Dec 2015 09:55:20 +0100 Original-Received: from localhost ([::1]:55142 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aEZ0y-0008Sy-6y for geh-help-gnu-emacs@m.gmane.org; Thu, 31 Dec 2015 03:55:20 -0500 Original-Path: usenet.stanford.edu!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 111 Original-X-Trace: individual.net fGmTQOrxqHIMlA8toRpOew6bhXkSUYNAkxWl/cX/X2eUAoDXfy Cancel-Lock: sha1:MWZkZThhYWJkZTZjMWZjNTA5MTk0OTZhMGFiYmVmMjRiMTU4YmYwMg== sha1:EgZNRvxwFVERdRWVDRwh2g50c9U= Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) Original-Xref: usenet.stanford.edu gnu.emacs.help:216258 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:108548 Archived-At: Emanuel Berg writes: > "Pascal J. Bourguignon" > writes: > >> You must remember the literal/immutable status of >> each item at each level. >> >> Since you are incapable of remembering it, you >> should assume that the whole input data is immutable >> and write purely functional code (ie. use append, >> not nconc) in general. > > OK, so you use `nconc' when you yourself create the > lists by hand and thus know they are not empty, all > the while using `list' and not ', and when done you > assign the result to a variable associated with a list > INSTEAD of using `nconc' directly because that > variable can hold the empty list, i.e. nil, which > `nconc' contrary to `append' cannot handle. And you do > this to save time! nconc can handle nil. But in that case, it doesn't modify it! It just return the nconc'ed list: (nconc nil nil (list 1 2 3) nil (list 3 4 5) nil) --> (1 2 3 3 4 5) (let ((list nil)) (list (nconc list nil (list 1 2 3) nil (list 3 4 5) nil) list)) --> ((1 2 3 3 4 5) ; returned nil) ; list is still bound to nil which cannot be mutated. (let ((list nil)) (list (setf list (nconc list nil (list 1 2 3) nil (list 3 4 5) nil)) list)) --> ((1 2 3 3 4 5) ; returned and set to list (1 2 3 3 4 5)) ; list has been set with setf, so it's ok. The only case where you could forget the setf, is when you just return the nconc'ed result: (defun f (list to-add) (setf list (nconc list to-add)) list) can be written just: (defun f (list to-add) (nconc list to-add)) But in such a case, notice that you will have to bind or use the result of f: (let ((list (list 1 2 3))) (setf list (f list (list 4 5 6))) list) --> (1 2 3 4 5 6) It's like with delete, but for the opposite reason: delete cannot transform a cons cell into the symbol nil: (delete 1 (list 1)) --> nil But in anycase, it is not specified how delete (or delq) modifies the list structure, so even: (let ((list (list 1 2 3 4 5))) (delete 3 list) list) is not guaranteed to return: (1 2 4 5) Instead, you have to write: (let ((list (list 1 2 3 4 5))) (setf list (delete 3 list)) list) --> (1 2 4 5) to ensure that list is bound to the wanted result of delete. It is general: when you have a function that mutate a structure and return the new structure, if the exact way how it mutates it is not specified or if it cannot always mutate it (eg for lists, when there's an impossible transition nil <-> cons cell), you have use the result of the function and cannot count on the mutation. So, to use a non-mutating function: (setf list (remove element list)) (setf list (append list tail)) and to use a mutating function: (setf list (delete element list)) (setf list (nconc list tail)) In both cases you must rebind the result. > Now I got it right! almost. ;-) -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk