all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Nicolas Richard <youngfrog@members.fsf.org>
To: Rolf Ade <rolf@pointsman.de>
Cc: emacs-tangents@gnu.org
Subject: Re: 2016-05-23 Emacs News
Date: Fri, 10 Jun 2016 16:55:45 +0200	[thread overview]
Message-ID: <87lh2dgkjy.fsf@ulb.ac.be> (raw)
In-Reply-To: <8737oldv21.fsf@linux-qg7d.fritz.box>

Rolf Ade <rolf@pointsman.de> writes:
> Is what the article demonstrates something special to the 'build-in'
> function sort or to emacs lisp? It would help me, if someone explains
> what happen in this example in other words (not in implementation detail
> but language concepts).


Note : meanwhile I saw Marcin posted a much shorter re-explanation... oh
well, I'll just post this anyway :)

I can't really do it in language-concepts because I don't know which
concepts you're familiar with, and more importantly because *I* am not
familiar enough with the concepts. I still hope it will be helpful :

It's related to two facts:
 (i)  sort changes the list inplace.
 (ii) the list is built at read-time instead of call-time, so that
 calling the same function multiple times re-uses the same list.

Now the steps that show the "problem". I'll try to explain very slowly.
I hope this is not too much details.

A) lisp code is actually a lisp list. In our example, the code that
   defines destructive-havoc is this :

   (defun destructive-havoc ()
     "Example of destructive havoc."
     (setq foo '(1 3 2))
     (message "before sort, foo is: %s" foo)
     (sort foo #'<)
     (message "after sort, foo is: %s" foo))
   
   That clearly looks like a list (first element would be the symbol
   `defun`, then the symbol `destructive`, then the empty list aka symbol
   `nil`, then a string, then four more lists). When you want to eval this
   code, emacs will first turn this list-looking-thing-in-your-buffer into
   an actual Lisp list. This is the reading step, aka read-time.
   
   Two more things to note in this step :
   - when emacs read '(1 3 2), it turned it into (quote (1 3 2)). This is
     what ' means. So this is in fact a list made of the symbol quote and
     the list (1 3 2). This list (1 3 2), I'll call it FooBar.
   - if you read the docstring of `quote`, it mentions something about «
     the value that was pre-constructed by the Lisp reader » and what it
     refers to, is exactly the FooBar list. But quote is not doing its
     job right now, so I'll come back to that later.


B) Since we asked, emacs will now proceed to evaluating this big list.
   This is what I called "call-time".
   How it does it is described in (info "(elisp) Intro Eval"), but
   basically it first looks at the first element of the list, and then
   decides what to do with the rest of the list. In this case the first
   element is `defun`, which is a symbol which denotes a macro, thus emacs
   will expand the macro and do its thing. At the end of this step,
   emacs now turned the symbol `destructive-havoc` into a function which
   holds the following list as its definition:
   (lambda nil "Example of destructive havoc." (setq foo (quote (1 3 2))) (message "before sort, foo is: %s" foo) (sort foo (function <)) (message "after sort, foo is: %s" foo))

   Here, note that a part of this list is in fact the bit that was created in step
   A, namely everything from (setq ... until the last paren. In
   particular, the (1 3 2) list in there is our FooBar.

C) next thing you'll be doing is evaluate (destructive-havoc). Again,
   emacs will read first (like step A) then evaluate (like step B) this
   code. This time, when evaluating, emacs sees destructive-havoc is symbol
   with a function definition, which means it'll evaluate the list
   contained in that function, i.e. the (lambda ...) form we have mentionned
   previously.

   Evaluating this lambda essentially means to evaluate all elements of the
   code inside, which is those :
     (setq foo (quote (1 3 2)))
     (message "before sort, foo is: %s" foo)
     (sort foo (function <))
     (message "after sort, foo is: %s" foo)

C1) The first thing is the setq, which gives `foo' the value obtained from
    evaluating (quote (1 3 2)). At this point, evaluating (quote (1 3 2))
    returns the value pre-constructed by the lisp reader in step A at the
    very beginning, which is FooBar.
C2) message constructs a string and shows it in the *Messages* buffer.
C3) sort sorts in-place, thus changing the data. IOW, FooBar was (1 3 2)
    but is now (1 2 3). It's the same list, but its content was changed.
C4) message constructs a string and shows it in the *Messages* buffer.

*at this point in time*, since the function definition contained FooBar
 and FooBar has had its content changed, the function inside
 destructive-havoc has somehow... changed too. It didn't change, really,
 but its content changed.

D) if you re-evaluate (destructive-havoc), the same steps happen again,
but since FooBar is now (1 2 3), what you see at step D2 is different.

Please note that despite the rather long post, I left out some details,
in particular (i) the difference between macro (or special form) and
function, (ii) the actual implementation of lists (as cons cells), (iii)
the byte-compilation and eager macro-expansion that might actually
happen when you evaluate things manually, even though you did not
request them.

HTH anyway.

-- 
Nicolas



  parent reply	other threads:[~2016-06-10 14:55 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-23 16:44 2016-05-23 Emacs News Sacha Chua
2016-06-10  0:04 ` Rolf Ade
2016-06-10 10:30   ` Nicolas Richard
2016-06-10 13:37     ` Rolf Ade
2016-06-10 13:52       ` Marcin Borkowski
2016-06-10 15:22         ` Rolf Ade
2016-06-10 16:45           ` John Mastro
2016-06-10 14:55       ` Nicolas Richard [this message]
2016-06-10 16:01         ` Rolf Ade

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87lh2dgkjy.fsf@ulb.ac.be \
    --to=youngfrog@members.fsf.org \
    --cc=emacs-tangents@gnu.org \
    --cc=rolf@pointsman.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.