help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

on ``An Introduction to Programming in Emacs Lisp''


From: Daniel Bastos
Subject: on ``An Introduction to Programming in Emacs Lisp''
Date: Tue, 26 Jan 2016 16:08:34 -0200

This is a report on minor typos and imperfections regarding

  An Introduction to Programming in Emacs Lisp
  By Robert J. Chassell, published by GNU Press
  Edition 3.10, 28 October 2009 ISBN 1-882114-43-4

I read it last December.  I had so much fun.  I'd like to take this
opportunity to thank the entire GNU project, not just because it
offers the highest quality, but also because of its social importance
and mainly because of its social importance.  (Incidentally, I regard
documentation as highly as the tools they document.  I think
documentation is the soul of science.  You can read documentation
written B.C. in the 21st century --- for instance, Plato.  Some
particular thanks goes to Robert Chassell for writing such a great
book on the excellent software the GNU EMACS is.)

The sections below name the node and the line in which the quoted
passage that deserves attention begins.  Before the quote, I make my
comment so that when you finally see the passage you already know
what to look for.

Some passages were very enjoyable.  Perhaps I can share some of my
enjoyment together with this report.  For those who don't mix fun with
work, you can begin after the line 

  Lots of great things took place in the 80s! 

Feel free to point me towards fixing these myself and providing a
patch.  I wouldn't mind doing it.  But I probably would need someone
to discuss the changes with.

(*) Great passages

(eintr) Simple Extension, 49

--8<---------------cut here---------------start------------->8---
   For example, recent versions blink their cursors by default.  I hate
such blinking, as well as other features, so I [...].
--8<---------------cut here---------------end--------------->8---

A man after my own heart!

(eintr) Columns of a graph, 155

--8<---------------cut here---------------start------------->8---
   (Incidentally, I don't know how you would learn of this function
without a book such as this.  It is possible to discover other
functions, like `search-forward' or `insert-rectangle', by guessing at
a part of their names and then using `apropos'.  Even though its base
in metaphor is clear--`apply' its first argument to the rest--I doubt a
novice would come up with that particular word when using `apropos' or
other aid.  Of course, I could be wrong; after all, the function was
first named by someone who had to invent it.)
--8<---------------cut here---------------end--------------->8---

(eintr) defcustom

--8<---------------cut here---------------start------------->8---
   The `custom-set-variables' function works somewhat differently than
a `setq'.  While I have never learned the differences, I modify the
`custom-set-variables' expressions in my `.emacs' file by hand:  I make
the changes in what appears to me to be a reasonable manner and have
not had any problems.  Others prefer to use the Customization command
and let Emacs do the work for them.
--8<---------------cut here---------------end--------------->8---

It's great to known what an expert thinks, even on personal matters.

(eintr) Beginning a .emacs File

--8<---------------cut here---------------start------------->8---
     ;;;; Bob's .emacs file
     ; Robert J. Chassell
     ; 26 September 1985

Look at that date!  I started this file a long time ago.  I have been
adding to it ever since.
--8<---------------cut here---------------end--------------->8---

Lots of great things took place in the 80s! 

(eintr) Emacs Initialization

--8<---------------cut here---------------start------------->8---
"You don't have to like Emacs to like it"--this seemingly paradoxical
statement is the secret of GNU Emacs.  The plain, `out of the box'
Emacs is a generic tool.  Most people who use it, customize it to suit
themselves.
--8<---------------cut here---------------end--------------->8---

Great passage!  But it turns out the last sentence seems to separate
subject from predicate with a comma, violating the English grammar.
(This passage therefore belongs to this section and the next.)

(*) Imperfections

(eintr) kill-new function, 51

I think that the line 

--8<---------------cut here---------------start------------->8---
  (setq kill-ring (cons string kill-ring)) 
--8<---------------cut here---------------end--------------->8---

appears by accident in the code of kill-new as displayed in the book.
It should not be there.  It's not in the source code of the function
and it doesn't make sense where it is displayed.  It seems a
yank-accident.

--8<---------------cut here---------------start------------->8---
   The critical lines are these:

       (if (and replace kill-ring)
           ;; then
           (setcar kill-ring string)
         ;; else
       (push string kill-ring)
         (setq kill-ring (cons string kill-ring))
         (if (> (length kill-ring) kill-ring-max)
             ;; avoid overly long kill ring
             (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
       (setq kill-ring-yank-pointer kill-ring)
       (if interprogram-cut-function
           (funcall interprogram-cut-function string (not replace))))
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Digression into C, 60

I think ``the Lisp'' was not intended.

--8<---------------cut here---------------start------------->8---
   * The sixth part is nearly like the argument that follows the
     `interactive' declaration in a function written in Lisp: a letter
     followed, perhaps, by a prompt.  The only difference from the Lisp
     is when the macro is called with no arguments.  Then you write a
     `0' (which is a `null string'), as in this macro.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Digression into C, 87

Perhaps ``del_range'' was not intended.  Perhaps ``del_range_1'' was
the intended function because it is the one it seems to be referred
to.

--8<---------------cut here---------------start------------->8---
   The `del_range_1' function actually deletes the text.  It is a
complex function we will not look into.  It updates the buffer and does
other things.  However, it is worth looking at the two arguments passed
to `del_range'.  These are `XINT (start)' and `XINT (end)'.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Symbols as Chest, 10

Typo.  From ``vice-verse'' to ``vice-versa''.

(*) (eintr) Every, 20

Typo? ``Here's an example'' was meant?

--8<---------------cut here---------------start------------->8---
   Here is example:
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Complete forward-sentence, 73

Likely a typo.  I think the author meant ``opoint'', not ``point''.
The let in question appears on line 43.  It binds the (point) value to
the symbol ``opoint''.

--8<---------------cut here---------------start------------->8---
   Next is a `let'.  That specifies the values of two local variables,
`point' and `sentence-end'.  The local value of point, from before the
search, is used in the `constrain-to-field' function which handles
forms and equivalents.  The `sentence-end' variable is set by the
`sentence-end' function.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) fwd-para while, 130

Typo.  Replace ``a the'' with ``the''.

--8<---------------cut here---------------start------------->8---
This `while' loop has us searching forward for `sp-parstart', which is
the combination of possible whitespace with a the local value of the
start of a paragraph or of a paragraph separator.  (The latter two are
within an expression starting `\(?:' so that they are not referenced by
the `match-beginning' function.)
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Divide and Conquer, l14

Typo? I'd think the proper English here would be ``the /number/ of
words in each function in a file''.  Or would it not?

--8<---------------cut here---------------start------------->8---
   * Second, write a function to list the numbers of words in each
     function in a file.  This function can use the
     `count-words-in-defun' function.

   * Third, write a function to list the numbers of words in each
     function in each of several files.  This entails automatically
     finding the various files, switching to them, and counting the
     words in the definitions within them.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Find a File, 18

In this paragraph, the passage "optional wildcards argument" should be
"optional WILDCARDS argument" to conform to the convention that
arguments should be written in uppercase.

--8<---------------cut here---------------start------------->8---
   According to its documentation as shown by `C-h f' (the
`describe-function' command), the `find-file-noselect' function reads
the named file into a buffer and returns the buffer.  (Its most recent
version includes an optional wildcards argument, too, as well as
another to read a file literally and an other you suppress warning
messages.  These optional arguments are irrelevant.)
--8<---------------cut here---------------end--------------->8---

(*) (eintr) lengths-list-many-files, 6

Missing preposition? I think the author meant "[t]he argument passed
/to/ the function is a list of files."

--8<---------------cut here---------------start------------->8---
   The design using a `while' loop is routine.  The argument passed the
function is a list of files.  As we saw earlier (*note Loop Example::),
you can write a `while' loop so that the body of the loop is evaluated
if such a list contains elements, but to exit the loop if the list is
empty.  For this design to work, the body of the loop must contain an
expression that shortens the list each time the body is evaluated, so
that eventually the list is empty.  The usual technique is to set the
value of the list to the value of the CDR of the list each time the
body is evaluated.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Columns of a graph, 35

Typo.  I think the author meant to write ``once took'' but wrote
``once too takes''.

--8<---------------cut here---------------start------------->8---
   What we want to look for is some command that prints or inserts
columns.  Very likely, the name of the function will contain either the
word `print' or the word `insert' or the word `column'.  Therefore, we
can simply type `M-x apropos RET print\|insert\|column RET' and look at
the result.  On my system, this command once too takes quite some time,
and then produced a list of 79 functions and variables.  Now it does
not take much time at all and produces a list of 211 functions and
variables.  Scanning down the list, the only function that looks as if
it might do the job is `insert-rectangle'.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Columns of a graph, 102

I'm not sure here.  I'd have written "we will have /to/ position point
/to/ the right number of lines".

--8<---------------cut here---------------start------------->8---
                     If this list consists solely of the requisite
number of asterisks, then we will have position point the right number
of lines above the base for the graph to print correctly.  This could
be difficult.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) Columns of a graph, 223

Typo.  The author meant ``you may want'' instead of ``you many want''.

--8<---------------cut here---------------start------------->8---
   As written, `column-of-graph' contains a major flaw: the symbols
used for the blank and for the marked entries in the column are
`hard-coded' as a space and asterisk.  This is fine for a prototype,
but you, or another user, may wish to use other symbols.  For example,
in testing the graph function, you many want to use a period in place
of the space, to make sure the point is being repositioned properly
each time the `insert-rectangle' function is called; or you might want
to substitute a `+' sign or other symbol for the asterisk.  You might
even want to make a graph-column that is more than one display column
wide.  The program should be more flexible.  The way to do that is to
replace the blank and the asterisk with two variables that we can call
`graph-blank' and `graph-symbol' and define those variables separately.
--8<---------------cut here---------------end--------------->8---

(*) (eintr) recursive-graph-body-print, 14

I believe the symbol ``from-position'' was not intended to be in this
function.  It might have been included by accident, since it is used
in another function, related to this one.  We have perhaps a variable
accidentally left over.

--8<---------------cut here---------------start------------->8---
     (defun recursive-graph-body-print (numbers-list)
       "Print a bar graph of the NUMBERS-LIST.
     The numbers-list consists of the Y-axis values."
       (let ((height (apply 'max numbers-list))
             (symbol-width (length graph-blank))
             from-position)
         (recursive-graph-body-print-internal
          numbers-list
          height
          symbol-width)))
--8<---------------cut here---------------end--------------->8---

(*) (eintr) defcustom

If I understood this correctly, the book mentions something I can't
find in GNU EMACS 24.3.1.  Here's the passage.

--8<---------------cut here---------------start------------->8---
     Using the customization command,  you can type:
  
       M-x customize
  
  and find that the group for editing files of data is called `data'.
  Enter that group.  Text Mode Hook is the first member.
--8<---------------cut here---------------end--------------->8---
  
I can't find it.  Here's what happens in my GNU EMACS.  I execute

  M-x customize 

and I see

  Emacs group: Customization of the One True Editor.

(Something with which I can agree!) Lots of groups are listed.

  Editing, Convenience, Files, Text, Data, ... 

I then click on ``Data''.  ``Text Mode Hook'' is not the first member.
In fact, it's not there at all.  I go back by pushing the button on
the ``parent group''.  Instead of ``Data'', I choose now the group
``Text''.  There I find ``Text Mode Hook'' as first member.

Therefore, I think the groups have been reorganized and the book is
now a tiny bit outdated.  Here's the complete definition of my version.

   GNU Emacs 24.3.1 (i386-mingw-nt6.1.7601) of 2013-03-17 on MARVIN.

(*) (eintr) debug, 57

I have an English question here.  Consider this passage.

--8<---------------cut here---------------start------------->8---
     However, suppose you are not quite certain what is going on?  You
  can read the complete backtrace.
--8<---------------cut here---------------end--------------->8---

Is it proper to question-mark that sentence? Is it what is called a
rhetoric question? Perhaps the author really meant to put a period
there.

(*) (eintr) recursive-count-words, 116

Another English question.

--8<---------------cut here---------------start------------->8---
   But already, we have an outline of the recursive counting function:
--8<---------------cut here---------------end--------------->8---

Is this comma okay there? I wouldn't have put it there.  I'd have
written

  But already we have an outline of the recursive counting function:

(*) (eintr) Columns of a graph, 276

A question, opinion.  It's not clear to me what the word ``value''
refers to in this paragraph.  The word ``value'' suddenly appears on
line 281.  Which value are we talking about? I can only suppose it's
the height of the graph at that point.  Perhaps that could be made
clearer.

--8<---------------cut here---------------start------------->8---
   If we wished, we could rewrite `column-of-graph' a third time to
provide optionally for a line graph as well as for a bar graph.  This
would not be hard to do.  One way to think of a line graph is that it
is no more than a bar graph in which the part of each bar that is below
the top is blank.  To construct a column for a line graph, the function
first constructs a list of blanks that is one shorter than the value,
then it uses `cons' to attach a graph symbol to the list; then it uses
`cons' again to attach the `top blanks' to the list.
--8<---------------cut here---------------end--------------->8---

(*) Text filling and visible-mode

A technical matter.  This is related to how paragraphs of the book are
displayed in the GNU EMACS.  The text isn't properly filled when there
are cross-references and visible-mode is disabled.  The filling is
made as if visible-mode were enabled.  Enabling it, it displays just fine.

A non-exhaustive list of various nodes where this can be seen:

  (eintr) forward-paragraph in brief, 26
  (eintr) fwd-para let, 39
  (eintr) Whitespace Bug, 165
  (eintr) recursive-count-words, 138
  (eintr) Sorting, 11
  (eintr) Counting function definitions, 51
  (eintr) Beginning a .emacs File, 13
  (eintr) Loading Files, l66
  (eintr) Autoload, l25
  (eintr) Conclusion, 89
  (eintr) the-the, 16
  (eintr) Words in a defun, l6

(*) (eintr) count-words-in-defun, 143

Another technical matter.  In this node, I could not run
count-words-defun successfully.  I'll say what I do, what happens and
what I expected to happen.

The defun that will be counted begins on line 143.  Following the
instructions that begin on line 139, I install count-words-in-defun,
count-words-defun, I set the keybinding and I position my cursor on
the ``7'' that appears inside the definition of multiply-by-seven.
IOW, my point is inside the defun.  I press ``C-c ='', which executes
count-words-defun.  My point is moved all the way up to the beginning
of the *info* buffer and the message displayed is

  The definition has 1 word or symbol.

I expected the message to display the correct number of words in the
defun (10 words or symbols) and point be moved to the end of the
defun.

I've narrowed the problem to beginning-of-defun.  In *info*, the defun
is indented by 5 spaces from the beginning of the line where the defun
begins.  As it turns out, beginning-of-defun is programmed not to find
such defun.  I believe this is the relevant regexp.

  (re-search-backward "^\\s(" ...

I interpret this as begin a line with ``(''.  If the defun does not
appear at the beginning of a line, this regexp will not match it.
Since my *info* buffer begins with ``(eintr)'', this is what is
matched.  Hence my point moves all the way to the beginning of buffer.

(*) (eintr) recursive-count-words, 160

Opinion.  For recursive functions, I find it more obvious when the
base case comes first.  The design of recursive-count-words puts the
base case as an else clause.

     (if DO-AGAIN-TEST-AND-NEXT-STEP-COMBINED
         ;; then
         RECURSIVE-CALL-RETURNING-COUNT
       ;; else
       RETURN-ZERO)

I would have done written it the following way.

     (if DO-AGAIN-TEST-TURNS-OUT-FALSE
         ;; then
         RETURN-ZERO
       ;; else
       RECURSIVE-CALL-RETURNING-COUNT)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]