From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Marcin Borkowski Newsgroups: gmane.emacs.help Subject: Re: Why doesn't nconc change my variable? Date: Sun, 05 Oct 2014 11:54:24 +0200 Message-ID: <87vbnylu3z.fsf@wmi.amu.edu.pl> References: <87y4svl2ku.fsf@wmi.amu.edu.pl> <3867d7c2-936d-4441-91d6-3b12dc959391@default> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1412502913 5045 80.91.229.3 (5 Oct 2014 09:55:13 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 5 Oct 2014 09:55:13 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Sun Oct 05 11:55:07 2014 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 1XaiWv-0002Y6-2z for geh-help-gnu-emacs@m.gmane.org; Sun, 05 Oct 2014 11:55:05 +0200 Original-Received: from localhost ([::1]:46889 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XaiWu-0001yF-MR for geh-help-gnu-emacs@m.gmane.org; Sun, 05 Oct 2014 05:55:04 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58791) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XaiWf-0001xv-Bj for help-gnu-emacs@gnu.org; Sun, 05 Oct 2014 05:54:55 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XaiWZ-0002hV-Lx for help-gnu-emacs@gnu.org; Sun, 05 Oct 2014 05:54:49 -0400 Original-Received: from msg.wmi.amu.edu.pl ([2001:808:114:2::50]:41413) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XaiWZ-0002hJ-0c for help-gnu-emacs@gnu.org; Sun, 05 Oct 2014 05:54:43 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by msg.wmi.amu.edu.pl (Postfix) with ESMTP id 463E55077D for ; Sun, 5 Oct 2014 11:54:40 +0200 (CEST) Original-Received: from msg.wmi.amu.edu.pl ([127.0.0.1]) by localhost (msg.wmi.amu.edu.pl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id x7aFXIpbO1HZ for ; Sun, 5 Oct 2014 11:54:40 +0200 (CEST) Original-Received: from localhost (111-128.echostar.pl [213.156.111.128]) by msg.wmi.amu.edu.pl (Postfix) with ESMTPSA id 5C2305077B for ; Sun, 5 Oct 2014 11:54:39 +0200 (CEST) In-reply-to: <3867d7c2-936d-4441-91d6-3b12dc959391@default> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:808:114:2::50 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:100282 Archived-At: On 2014-10-05, at 03:58, Drew Adams wrote: >> (setq my-list ()) >> (nconc my-list '("wtf")) >> >> and my-list is still nil. If, OTOH, I do >> (setq my-list ()) >> (setq my-list (nconc my-list '("wtf"))) >> >> my-list is ("wtf"). >> >> Why is that so? I though nconc is supposed to change all its >> arguments but the last one. Is the latter construct a correct >> way of adding an element at the end of the list? > > No, it's not supposed to do that. You discovered just what it > does do. And you could have discovered it earlier by reading > some doc. See the Elisp manual, node `Rearrangement' (found by > doing `i nconc' in the manual). I did read it. And a few times, for that matter. You see, one of the worst intellectual mistakes you can make is to have a wrong mental model of something. This seems to be the case here, and that's why I really want to grok this issue. > See also node `Sets and Lists', in particular this (about `delq', > but the same idea applies to other destructive list operations): > > Note that `(delq 'c sample-list)' modifies `sample-list' to splice > out the third element, but `(delq 'a sample-list)' does not splice > anything--it just returns a shorter list. Don't assume that a variable > which formerly held the argument LIST now has fewer elements, or that > it still holds the original list! Instead, save the result of `delq' > and use that. Most often we store the result back into the variable > that held the original list: > > (setq flowers (delq 'rose flowers)) That I didn't read earlier; I've read it now, and still don't get it. Sorry. (Edit: while I was writing the rest of this post, things apparently got more clear, but I'll leave the rest, since if I'm right, this might be (hopefully) instructive for others reading it, and I might even want to save it to post it on my blog.) Now I have two choices. One is to install the C source and try to read it. This I cannot do now (time constraints, and while I did learn some C, it was, what, fifteen years ago or so). That's why I'm asking here. Please bear with me. This should also be good for Emacs, since it may be the case that if I cannot understand the manual, someone else might have troubles with that, too, so maybe the manual is buggy. What I thought was essentially this: under the hood, a list is a pointer (using C terminology) to a cons cell. The car of the cons cell is a pointer to some data (say, a string), and the cdr - a pointer to the next cons cell. What I thought is that if you say, e.g., (setq my-list ("hello" "world")) and then (nconc my-list '("wtf")) then my-list points to the list ("hello" "world" "wtf"). This seems to be indeed the case. (And the wtf's get added if I repeat the nconc step - I confirmed that experimentally.) Now, when I say (setq my-list (list)) (or (setq list ())) then nconc'ing '("wtf")'s onto it (as before) does not have the same effect. Why on earth is that!? Does it mean that Pascal's earlier response was right? Now that I'm thinking about it, this makes sense: an empty list is (I would guess) a NUL pointer, so nconc'ing has not the meaning of "changing the cdr" but rather of "returning a brand new cons cell". This in turn means that this sentence from the manual: "Instead, the last CDR of each of the LISTS is changed to refer to the following list." is misleading: if I have an empty list, there's no cdr to change, and that's why nconc would (probably) branch to a different subroutine and create a brand new cons cell. (Now that I'm wondering what the implementation might actually be, I'm more and more tempted to look at the C source. This is probably a good sign.) So, now I have some more questions and one suggestion. (More knowledge always brings more questions, right?) 1. Do I get it correctly that the "destructiveness" of some functions (like nconc) does /not/ mean that they /change/ some of their arguments, but only that they /may/ do it, and that relying on that is risky? 2. Do I get it correctly that what Pascal called "a nil symbol" is just NUL under the hood? Does it mean that there's no difference between (), nil and the result of (list) (as opposed to the results of calling list twice with the same arguments)? (They seem to be `eq', as I've just checked.) 3. What is the "canonical" way to append an element to a list, in the sense that I have a variable containing (=pointing to?) a list, I want it to point to a list one element longer? And, while at that, what is the "canonical" way to /prepend/ an element to a list (is it `push'?) 4. (This is the suggestion.) If the above is right, could someone make it more clear in the manual (or point me to the place in the manual where it is actually stated)? TIA, -- Marcin Borkowski http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski Adam Mickiewicz University