[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When the Lisp interpreter evaluates a list, it looks to see whether the first symbol on the list has a function definition attached to it; or, put another way, whether the symbol points to a function definition. If it does, the computer carries out the instructions in the definition. A symbol that has a function definition is called, simply, a function (although, properly speaking, the definition is the function and the symbol refers to it.)
An Aside about Primitive Functions | ||
3.1 The defun Special Form | The defun special form. | |
3.2 Install a Function Definition | Install a function definition. | |
3.3 Make a Function Interactive | Making a function interactive. | |
3.4 Different Options for interactive | Different options for interactive . | |
3.5 Install Code Permanently | Installing code permanently. | |
3.6 let | Creating and initializing local variables. | |
3.7 The if Special Form | What if? | |
3.8 If--then--else Expressions | If--then--else expressions. | |
3.9 Truth and Falsehood in Emacs Lisp | What Lisp considers false and true. | |
3.10 save-excursion | Keeping track of point, mark, and buffer. | |
3.11 Review | ||
3.12 Exercises |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
All functions are defined in terms of other functions, except for a few primitive functions that are written in the C programming language. When you write functions' definitions, you will write them in Emacs Lisp and use other functions as your building blocks. Some of the functions you will use will themselves be written in Emacs Lisp (perhaps by you) and some will be primitives written in C. The primitive functions are used exactly like those written in Emacs Lisp and behave like them. They are written in C so we can easily run GNU Emacs on any computer that has sufficient power and can run C.
Let me re-emphasize this: when you write code in Emacs Lisp, you do not distinguish between the use of functions written in C and the use of functions written in Emacs Lisp. The difference is irrelevant. I mention the distinction only because it is interesting to know. Indeed, unless you investigate, you won't know whether an already-written function is written in Emacs Lisp or C.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
defun
Special Form
In Lisp, a symbol such as mark-whole-buffer
has code attached to
it that tells the computer what to do when the function is called.
This code is called the function definition and is created by
evaluating a Lisp expression that starts with the symbol defun
(which is an abbreviation for define function). Because
defun
does not evaluate its arguments in the usual way, it is
called a special form.
In subsequent sections, we will look at function definitions from the
Emacs source code, such as mark-whole-buffer
. In this section,
we will describe a simple function definition so you can see how it
looks. This function definition uses arithmetic because it makes for a
simple example. Some people dislike examples using arithmetic; however,
if you are such a person, do not despair. Hardly any of the code we
will study in the remainder of this introduction involves arithmetic or
mathematics. The examples mostly involve text in one way or another.
A function definition has up to five parts following the word
defun
:
()
.
It is helpful to think of the five parts of a function definition as being organized in a template, with slots for each part:
(defun function-name (arguments...) "optional-documentation..." (interactive argument-passing-info) ; optional body...) |
As an example, here is the code for a function that multiplies its argument by 7. (This example is not interactive. See section Making a Function Interactive, for that information.)
(defun multiply-by-seven (number) "Multiply NUMBER by seven." (* 7 number)) |
This definition begins with a parenthesis and the symbol defun
,
followed by the name of the function.
The name of the function is followed by a list that contains the
arguments that will be passed to the function. This list is called
the argument list. In this example, the list has only one
element, the symbol, number
. When the function is used, the
symbol will be bound to the value that is used as the argument to the
function.
Instead of choosing the word number
for the name of the argument,
I could have picked any other name. For example, I could have chosen
the word multiplicand
. I picked the word `number' because it
tells what kind of value is intended for this slot; but I could just as
well have chosen the word `multiplicand' to indicate the role that the
value placed in this slot will play in the workings of the function. I
could have called it foogle
, but that would have been a bad
choice because it would not tell humans what it means. The choice of
name is up to the programmer and should be chosen to make the meaning of
the function clear.
Indeed, you can choose any name you wish for a symbol in an argument
list, even the name of a symbol used in some other function: the name
you use in an argument list is private to that particular definition.
In that definition, the name refers to a different entity than any use
of the same name outside the function definition. Suppose you have a
nick-name `Shorty' in your family; when your family members refer to
`Shorty', they mean you. But outside your family, in a movie, for
example, the name `Shorty' refers to someone else. Because a name in an
argument list is private to the function definition, you can change the
value of such a symbol inside the body of a function without changing
its value outside the function. The effect is similar to that produced
by a let
expression. (See section let
.)
The argument list is followed by the documentation string that
describes the function. This is what you see when you type
C-h f and the name of a function. Incidentally, when you
write a documentation string like this, you should make the first line
a complete sentence since some commands, such as apropos
, print
only the first line of a multi-line documentation string. Also, you
should not indent the second line of a documentation string, if you
have one, because that looks odd when you use C-h f
(describe-function
). The documentation string is optional, but
it is so useful, it should be included in almost every function you
write.
The third line of the example consists of the body of the function
definition. (Most functions' definitions, of course, are longer than
this.) In this function, the body is the list, (* 7 number)
, which
says to multiply the value of number by 7. (In Emacs Lisp,
*
is the function for multiplication, just as +
is the
function for addition.)
When you use the multiply-by-seven
function, the argument
number
evaluates to the actual number you want used. Here is an
example that shows how multiply-by-seven
is used; but don't try
to evaluate this yet!
(multiply-by-seven 3) |
The symbol number
, specified in the function definition in the
next section, is given or "bound to" the value 3 in the actual use of
the function. Note that although number
was inside parentheses
in the function definition, the argument passed to the
multiply-by-seven
function is not in parentheses. The
parentheses are written in the function definition so the computer can
figure out where the argument list ends and the rest of the function
definition begins.
If you evaluate this example, you are likely to get an error message. (Go ahead, try it!) This is because we have written the function definition, but not yet told the computer about the definition--we have not yet installed (or `loaded') the function definition in Emacs. Installing a function is the process that tells the Lisp interpreter the definition of the function. Installation is described in the next section.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If you are reading this inside of Info in Emacs, you can try out the
multiply-by-seven
function by first evaluating the function
definition and then evaluating (multiply-by-seven 3)
. A copy of
the function definition follows. Place the cursor after the last
parenthesis of the function definition and type C-x C-e. When you
do this, multiply-by-seven
will appear in the echo area. (What
this means is that when a function definition is evaluated, the value it
returns is the name of the defined function.) At the same time, this
action installs the function definition.
(defun multiply-by-seven (number) "Multiply NUMBER by seven." (* 7 number)) |
By evaluating this defun
, you have just installed
multiply-by-seven
in Emacs. The function is now just as much a
part of Emacs as forward-word
or any other editing function you
use. (multiply-by-seven
will stay installed until you quit
Emacs. To reload code automatically whenever you start Emacs, see
Installing Code Permanently.)
The effect of installation | ||
3.2.1 Change a Function Definition | How to change a function definition. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can see the effect of installing multiply-by-seven
by
evaluating the following sample. Place the cursor after the following
expression and type C-x C-e. The number 21 will appear in the
echo area.
(multiply-by-seven 3) |
If you wish, you can read the documentation for the function by typing
C-h f (describe-function
) and then the name of the
function, multiply-by-seven
. When you do this, a
`*Help*' window will appear on your screen that says:
multiply-by-seven: Multiply NUMBER by seven. |
(To return to a single window on your screen, type C-x 1.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If you want to change the code in multiply-by-seven
, just rewrite
it. To install the new version in place of the old one, evaluate the
function definition again. This is how you modify code in Emacs. It is
very simple.
As an example, you can change the multiply-by-seven
function to
add the number to itself seven times instead of multiplying the number
by seven. It produces the same answer, but by a different path. At
the same time, we will add a comment to the code; a comment is text
that the Lisp interpreter ignores, but that a human reader may find
useful or enlightening. The comment is that this is the "second
version".
(defun multiply-by-seven (number) ; Second version. "Multiply NUMBER by seven." (+ number number number number number number number)) |
The comment follows a semicolon, `;'. In Lisp, everything on a line that follows a semicolon is a comment. The end of the line is the end of the comment. To stretch a comment over two or more lines, begin each line with a semicolon.
See section Beginning a `.emacs' File, and section `Comments' in The GNU Emacs Lisp Reference Manual, for more about comments.
You can install this version of the multiply-by-seven
function by
evaluating it in the same way you evaluated the first function: place
the cursor after the last parenthesis and type C-x C-e.
In summary, this is how you write code in Emacs Lisp: you write a function; install it; test it; and then make fixes or enhancements and install it again.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You make a function interactive by placing a list that begins with
the special form interactive
immediately after the
documentation. A user can invoke an interactive function by typing
M-x and then the name of the function; or by typing the keys to
which it is bound, for example, by typing C-n for
next-line
or C-x h for mark-whole-buffer
.
Interestingly, when you call an interactive function interactively, the value returned is not automatically displayed in the echo area. This is because you often call an interactive function for its side effects, such as moving forward by a word or line, and not for the value returned. If the returned value were displayed in the echo area each time you typed a key, it would be very distracting.
An Interactive multiply-by-seven , An Overview | An overview. | |
3.3.1 An Interactive multiply-by-seven | The interactive version. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
multiply-by-seven
, An Overview
Both the use of the special form interactive
and one way to
display a value in the echo area can be illustrated by creating an
interactive version of multiply-by-seven
.
Here is the code:
(defun multiply-by-seven (number) ; Interactive version. "Multiply NUMBER by seven." (interactive "p") (message "The result is %d" (* 7 number))) |
You can install this code by placing your cursor after it and typing C-x C-e. The name of the function will appear in your echo area. Then, you can use this code by typing C-u and a number and then typing M-x multiply-by-seven and pressing RET. The phrase `The result is ...' followed by the product will appear in the echo area.
Speaking more generally, you invoke a function like this in either of two ways:
Both the examples just mentioned work identically to move point forward
three sentences. (Since multiply-by-seven
is not bound to a key,
it could not be used as an example of key binding.)
(See section Some Keybindings, to learn how to bind a command to a key.)
A prefix argument is passed to an interactive function by typing the META key followed by a number, for example, M-3 M-e, or by typing C-u and then a number, for example, C-u 3 M-e (if you type C-u without a number, it defaults to 4).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
multiply-by-seven
Let's look at the use of the special form interactive
and then at
the function message
in the interactive version of
multiply-by-seven
. You will recall that the function definition
looks like this:
(defun multiply-by-seven (number) ; Interactive version. "Multiply NUMBER by seven." (interactive "p") (message "The result is %d" (* 7 number))) |
In this function, the expression, (interactive "p")
, is a list of
two elements. The "p"
tells Emacs to pass the prefix argument to
the function and use its value for the argument of the function.
The argument will be a number. This means that the symbol
number
will be bound to a number in the line:
(message "The result is %d" (* 7 number)) |
For example, if your prefix argument is 5, the Lisp interpreter will evaluate the line as if it were:
(message "The result is %d" (* 7 5)) |
(If you are reading this in GNU Emacs, you can evaluate this expression
yourself.) First, the interpreter will evaluate the inner list, which
is (* 7 5)
. This returns a value of 35. Next, it
will evaluate the outer list, passing the values of the second and
subsequent elements of the list to the function message
.
As we have seen, message
is an Emacs Lisp function especially
designed for sending a one line message to a user. (See section The message
function.)
In summary, the message
function prints its first argument in the
echo area as is, except for occurrences of `%d', `%s', or
`%c'. When it sees one of these control sequences, the function
looks to the second and subsequent arguments and prints the value of the
argument in the location in the string where the control sequence is
located.
In the interactive multiply-by-seven
function, the control string
is `%d', which requires a number, and the value returned by
evaluating (* 7 5)
is the number 35. Consequently, the number 35
is printed in place of the `%d' and the message is `The result
is 35'.
(Note that when you call the function multiply-by-seven
, the
message is printed without quotes, but when you call message
, the
text is printed in double quotes. This is because the value returned by
message
is what appears in the echo area when you evaluate an
expression whose first element is message
; but when embedded in a
function, message
prints the text as a side effect without
quotes.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
interactive
In the example, multiply-by-seven
used "p"
as the
argument to interactive
. This argument told Emacs to interpret
your typing either C-u followed by a number or META
followed by a number as a command to pass that number to the function
as its argument. Emacs has more than twenty characters predefined for
use with interactive
. In almost every case, one of these
options will enable you to pass the right information interactively to
a function. (See section `Code Characters for interactive
' in The GNU Emacs Lisp Reference Manual.)
For example, the character `r' causes Emacs to pass the beginning and end of the region (the current values of point and mark) to the function as two separate arguments. It is used as follows:
(interactive "r") |
On the other hand, a `B' tells Emacs to ask for the name of a
buffer that will be passed to the function. When it sees a `B',
Emacs will ask for the name by prompting the user in the minibuffer,
using a string that follows the `B', as in "BAppend to
buffer: "
. Not only will Emacs prompt for the name, but Emacs will
complete the name if you type enough of it and press TAB.
A function with two or more arguments can have information passed to
each argument by adding parts to the string that follows
interactive
. When you do this, the information is passed to
each argument in the same order it is specified in the
interactive
list. In the string, each part is separated from
the next part by a `\n', which is a newline. For example, you
could follow "BAppend to buffer: "
with a `\n') and an
`r'. This would cause Emacs to pass the values of point and mark
to the function as well as prompt you for the buffer--three arguments
in all.
In this case, the function definition would look like the following,
where buffer
, start
, and end
are the symbols to
which interactive
binds the buffer and the current values of the
beginning and ending of the region:
(defun name-of-function (buffer start end) "documentation..." (interactive "BAppend to buffer: \nr") body-of-function...) |
(The space after the colon in the prompt makes it look better when you
are prompted. The append-to-buffer
function looks exactly like
this. See section The Definition of append-to-buffer
.)
If a function does not have arguments, then interactive
does not
require any. Such a function contains the simple expression
(interactive)
. The mark-whole-buffer
function is like
this.
Alternatively, if the special letter-codes are not right for your
application, you can pass your own arguments to interactive
as
a list. See section `Using Interactive
' in The GNU Emacs Lisp Reference Manual, for more information about this advanced
technique.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you install a function definition by evaluating it, it will stay installed until you quit Emacs. The next time you start a new session of Emacs, the function will not be installed unless you evaluate the function definition again.
At some point, you may want to have code installed automatically whenever you start a new session of Emacs. There are several ways of doing this:
load
function to cause Emacs to evaluate and thereby install each of the
functions in the files.
See section Loading Files.
Finally, if you have code that everyone who uses Emacs may want, you can post it on a computer network or send a copy to the Free Software Foundation. (When you do this, please license the code and its documentation under a license that permits other people to run, copy, study, modify, and redistribute the code and which protects you from having your work taken from you.) If you send a copy of your code to the Free Software Foundation, and properly protect yourself and others, it may be included in the next release of Emacs. In large part, this is how Emacs has grown over the past years, by donations.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
let
The let
expression is a special form in Lisp that you will need
to use in most function definitions.
let
is used to attach or bind a symbol to a value in such a way
that the Lisp interpreter will not confuse the variable with a
variable of the same name that is not part of the function.
To understand why the let
special form is necessary, consider
the situation in which you own a home that you generally refer to as
`the house', as in the sentence, "The house needs painting." If you
are visiting a friend and your host refers to `the house', he is
likely to be referring to his house, not yours, that is, to a
different house.
If your friend is referring to his house and you think he is referring
to your house, you may be in for some confusion. The same thing could
happen in Lisp if a variable that is used inside of one function has
the same name as a variable that is used inside of another function,
and the two are not intended to refer to the same value. The
let
special form prevents this kind of confusion.
let Prevents Confusion | ||
3.6.1 The Parts of a let Expression | ||
3.6.2 Sample let Expression | ||
3.6.3 Uninitialized Variables in a let Statement |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
let
Prevents Confusion
The let
special form prevents confusion. let
creates a
name for a local variable that overshadows any use of the same
name outside the let
expression. This is like understanding
that whenever your host refers to `the house', he means his house, not
yours. (Symbols used in argument lists work the same way.
See section The defun
Special Form.)
Local variables created by a let
expression retain their value
only within the let
expression itself (and within
expressions called within the let
expression); the local
variables have no effect outside the let
expression.
Another way to think about let
is that it is like a setq
that is temporary and local. The values set by let
are
automatically undone when the let
is finished. The setting
only effects expressions that are inside the bounds of the let
expression. In computer science jargon, we would say "the binding of
a symbol is visible only in functions called in the let
form;
in Emacs Lisp, scoping is dynamic, not lexical."
let
can create more than one variable at once. Also,
let
gives each variable it creates an initial value, either a
value specified by you, or nil
. (In the jargon, this is called
`binding the variable to the value'.) After let
has created
and bound the variables, it executes the code in the body of the
let
, and returns the value of the last expression in the body,
as the value of the whole let
expression. (`Execute' is a jargon
term that means to evaluate a list; it comes from the use of the word
meaning `to give practical effect to' (Oxford English
Dictionary). Since you evaluate an expression to perform an action,
`execute' has evolved as a synonym to `evaluate'.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
let
Expression
A let
expression is a list of three parts. The first part is
the symbol let
. The second part is a list, called a
varlist, each element of which is either a symbol by itself or a
two-element list, the first element of which is a symbol. The third
part of the let
expression is the body of the let
. The
body usually consists of one or more lists.
A template for a let
expression looks like this:
(let varlist body...) |
The symbols in the varlist are the variables that are given initial
values by the let
special form. Symbols by themselves are given
the initial value of nil
; and each symbol that is the first
element of a two-element list is bound to the value that is returned
when the Lisp interpreter evaluates the second element.
Thus, a varlist might look like this: (thread (needles 3))
. In
this case, in a let
expression, Emacs binds the symbol
thread
to an initial value of nil
, and binds the symbol
needles
to an initial value of 3.
When you write a let
expression, what you do is put the
appropriate expressions in the slots of the let
expression
template.
If the varlist is composed of two-element lists, as is often the case,
the template for the let
expression looks like this:
(let ((variable value) (variable value) ...) body...) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
let
Expression
The following expression creates and gives initial values
to the two variables zebra
and tiger
. The body of the
let
expression is a list which calls the message
function.
(let ((zebra 'stripes) (tiger 'fierce)) (message "One kind of animal has %s and another is %s." zebra tiger)) |
Here, the varlist is ((zebra 'stripes) (tiger 'fierce))
.
The two variables are zebra
and tiger
. Each variable is
the first element of a two-element list and each value is the second
element of its two-element list. In the varlist, Emacs binds the
variable zebra
to the value stripes
, and binds the
variable tiger
to the value fierce
. In this example,
both values are symbols preceded by a quote. The values could just as
well have been another list or a string. The body of the let
follows after the list holding the variables. In this example, the body
is a list that uses the message
function to print a string in
the echo area.
You may evaluate the example in the usual fashion, by placing the cursor after the last parenthesis and typing C-x C-e. When you do this, the following will appear in the echo area:
"One kind of animal has stripes and another is fierce." |
As we have seen before, the message
function prints its first
argument, except for `%s'. In this example, the value of the variable
zebra
is printed at the location of the first `%s' and the
value of the variable tiger
is printed at the location of the
second `%s'.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
let
Statement
If you do not bind the variables in a let
statement to specific
initial values, they will automatically be bound to an initial value of
nil
, as in the following expression:
(let ((birch 3) pine fir (oak 'some)) (message "Here are %d variables with %s, %s, and %s value." birch pine fir oak)) |
Here, the varlist is ((birch 3) pine fir (oak 'some))
.
If you evaluate this expression in the usual way, the following will appear in your echo area:
"Here are 3 variables with nil, nil, and some value." |
In this example, Emacs binds the symbol birch
to the number 3,
binds the symbols pine
and fir
to nil
, and binds
the symbol oak
to the value some
.
Note that in the first part of the let
, the variables pine
and fir
stand alone as atoms that are not surrounded by
parentheses; this is because they are being bound to nil
, the
empty list. But oak
is bound to some
and so is a part of
the list (oak 'some)
. Similarly, birch
is bound to the
number 3 and so is in a list with that number. (Since a number
evaluates to itself, the number does not need to be quoted. Also, the
number is printed in the message using a `%d' rather than a
`%s'.) The four variables as a group are put into a list to
delimit them from the body of the let
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
if
Special Form
A third special form, in addition to defun
and let
, is the
conditional if
. This form is used to instruct the computer to
make decisions. You can write function definitions without using
if
, but it is used often enough, and is important enough, to be
included here. It is used, for example, in the code for the
function beginning-of-buffer
.
The basic idea behind an if
, is that "if a test is true,
then an expression is evaluated." If the test is not true, the
expression is not evaluated. For example, you might make a decision
such as, "if it is warm and sunny, then go to the beach!"
if in more detail | ||
3.7.1 The type-of-animal Function in Detail | An example of an if expression. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
if
in more detail
An if
expression written in Lisp does not use the word `then';
the test and the action are the second and third elements of the list
whose first element is if
. Nonetheless, the test part of an
if
expression is often called the if-part and the second
argument is often called the then-part.
Also, when an if
expression is written, the true-or-false-test
is usually written on the same line as the symbol if
, but the
action to carry out if the test is true, the "then-part", is written
on the second and subsequent lines. This makes the if
expression easier to read.
(if true-or-false-test action-to-carry-out-if-test-is-true) |
The true-or-false-test will be an expression that is evaluated by the Lisp interpreter.
Here is an example that you can evaluate in the usual manner. The test is whether the number 5 is greater than the number 4. Since it is, the message `5 is greater than 4!' will be printed.
(if (> 5 4) ; if-part (message "5 is greater than 4!")) ; then-part |
(The function >
tests whether its first argument is greater than
its second argument and returns true if it is.)
Of course, in actual use, the test in an if
expression will not
be fixed for all time as it is by the expression (> 5 4)
.
Instead, at least one of the variables used in the test will be bound to
a value that is not known ahead of time. (If the value were known ahead
of time, we would not need to run the test!)
For example, the value may be bound to an argument of a function
definition. In the following function definition, the character of the
animal is a value that is passed to the function. If the value bound to
characteristic
is fierce
, then the message, `It's a
tiger!' will be printed; otherwise, nil
will be returned.
(defun type-of-animal (characteristic) "Print message in echo area depending on CHARACTERISTIC. If the CHARACTERISTIC is the symbol `fierce', then warn of a tiger." (if (equal characteristic 'fierce) (message "It's a tiger!"))) |
If you are reading this inside of GNU Emacs, you can evaluate the function definition in the usual way to install it in Emacs, and then you can evaluate the following two expressions to see the results:
(type-of-animal 'fierce) (type-of-animal 'zebra) |
When you evaluate (type-of-animal 'fierce)
, you will see the
following message printed in the echo area: "It's a tiger!"
; and
when you evaluate (type-of-animal 'zebra)
you will see nil
printed in the echo area.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
type-of-animal
Function in Detail
Let's look at the type-of-animal
function in detail.
The function definition for type-of-animal
was written by filling
the slots of two templates, one for a function definition as a whole, and
a second for an if
expression.
The template for every function that is not interactive is:
(defun name-of-function (argument-list) "documentation..." body...) |
The parts of the function that match this template look like this:
(defun type-of-animal (characteristic)
"Print message in echo area depending on CHARACTERISTIC.
If the CHARACTERISTIC is the symbol `fierce',
then warn of a tiger."
body: the |
The name of function is type-of-animal
; it is passed the value
of one argument. The argument list is followed by a multi-line
documentation string. The documentation string is included in the
example because it is a good habit to write documentation string for
every function definition. The body of the function definition
consists of the if
expression.
The template for an if
expression looks like this:
(if true-or-false-test action-to-carry-out-if-the-test-returns-true) |
In the type-of-animal
function, the code for the if
looks like this:
(if (equal characteristic 'fierce) (message "It's a tiger!"))) |
Here, the true-or-false-test is the expression:
(equal characteristic 'fierce) |
In Lisp, equal
is a function that determines whether its first
argument is equal to its second argument. The second argument is the
quoted symbol 'fierce
and the first argument is the value of the
symbol characteristic
---in other words, the argument passed to
this function.
In the first exercise of type-of-animal
, the argument
fierce
is passed to type-of-animal
. Since fierce
is equal to fierce
, the expression, (equal characteristic
'fierce)
, returns a value of true. When this happens, the if
evaluates the second argument or then-part of the if
:
(message "It's tiger!")
.
On the other hand, in the second exercise of type-of-animal
, the
argument zebra
is passed to type-of-animal
. zebra
is not equal to fierce
, so the then-part is not evaluated and
nil
is returned by the if
expression.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An if
expression may have an optional third argument, called
the else-part, for the case when the true-or-false-test returns
false. When this happens, the second argument or then-part of the
overall if
expression is not evaluated, but the third or
else-part is evaluated. You might think of this as the cloudy
day alternative for the decision `if it is warm and sunny, then go to
the beach, else read a book!".
The word "else" is not written in the Lisp code; the else-part of an
if
expression comes after the then-part. In the written Lisp, the
else-part is usually written to start on a line of its own and is
indented less than the then-part:
(if true-or-false-test action-to-carry-out-if-the-test-returns-true action-to-carry-out-if-the-test-returns-false) |
For example, the following if
expression prints the message `4
is not greater than 5!' when you evaluate it in the usual way:
(if (> 4 5) ; if-part (message "5 is greater than 4!") ; then-part (message "4 is not greater than 5!")) ; else-part |
Note that the different levels of indentation make it easy to
distinguish the then-part from the else-part. (GNU Emacs has several
commands that automatically indent if
expressions correctly.
See section GNU Emacs Helps You Type Lists.)
We can extend the type-of-animal
function to include an
else-part by simply incorporating an additional part to the if
expression.
You can see the consequences of doing this if you evaluate the following
version of the type-of-animal
function definition to install it
and then evaluate the two subsequent expressions to pass different
arguments to the function.
(defun type-of-animal (characteristic) ; Second version. "Print message in echo area depending on CHARACTERISTIC. If the CHARACTERISTIC is the symbol `fierce', then warn of a tiger; else say it's not fierce." (if (equal characteristic 'fierce) (message "It's a tiger!") (message "It's not fierce!"))) |
(type-of-animal 'fierce) (type-of-animal 'zebra) |
When you evaluate (type-of-animal 'fierce)
, you will see the
following message printed in the echo area: "It's a tiger!"
; but
when you evaluate (type-of-animal 'zebra)
, you will see
"It's not fierce!"
.
(Of course, if the characteristic were ferocious
, the
message "It's not fierce!"
would be printed; and it would be
misleading! When you write code, you need to take into account the
possibility that some such argument will be tested by the if
and
write your program accordingly.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There is an important aspect to the truth test in an if
expression. So far, we have spoken of `true' and `false' as values of
predicates as if they were new kinds of Emacs Lisp objects. In fact,
`false' is just our old friend nil
. Anything else--anything
at all--is `true'.
The expression that tests for truth is interpreted as true
if the result of evaluating it is a value that is not nil
. In
other words, the result of the test is considered true if the value
returned is a number such as 47, a string such as "hello"
, or a
symbol (other than nil
) such as flowers
, or a list, or
even a buffer!
An explanation of nil | nil has two meanings. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
nil
Before illustrating a test for truth, we need an explanation of nil
.
In Emacs Lisp, the symbol nil
has two meanings. First, it means the
empty list. Second, it means false and is the value returned when a
true-or-false-test tests false. nil
can be written as an empty
list, ()
, or as nil
. As far as the Lisp interpreter is
concerned, ()
and nil
are the same. Humans, however, tend
to use nil
for false and ()
for the empty list.
In Emacs Lisp, any value that is not nil
---is not the empty
list--is considered true. This means that if an evaluation returns
something that is not an empty list, an if
expression will test
true. For example, if a number is put in the slot for the test, it
will be evaluated and will return itself, since that is what numbers
do when evaluated. In this conditional, the if
expression will
test true. The expression tests false only when nil
, an empty
list, is returned by evaluating the expression.
You can see this by evaluating the two expressions in the following examples.
In the first example, the number 4 is evaluated as the test in the
if
expression and returns itself; consequently, the then-part
of the expression is evaluated and returned: `true' appears in
the echo area. In the second example, the nil
indicates false;
consequently, the else-part of the expression is evaluated and
returned: `false' appears in the echo area.
(if 4 'true 'false) (if nil 'true 'false) |
Incidentally, if some other useful value is not available for a test that
returns true, then the Lisp interpreter will return the symbol t
for true. For example, the expression (> 5 4)
returns t
when evaluated, as you can see by evaluating it in the usual way:
(> 5 4) |
On the other hand, this function returns nil
if the test is false.
(> 4 5) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
save-excursion
The save-excursion
function is the fourth and final special form
that we will discuss in this chapter.
In Emacs Lisp programs used for editing, the save-excursion
function is very common. It saves the location of point and mark,
executes the body of the function, and then restores point and mark to
their previous positions if their locations were changed. Its primary
purpose is to keep the user from being surprised and disturbed by
unexpected movement of point or mark.
Point and Mark | A review of various locations. | |
3.10.1 Template for a save-excursion Expression |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Before discussing save-excursion
, however, it may be useful
first to review what point and mark are in GNU Emacs. Point is
the current location of the cursor. Wherever the cursor
is, that is point. More precisely, on terminals where the cursor
appears to be on top of a character, point is immediately before the
character. In Emacs Lisp, point is an integer. The first character in
a buffer is number one, the second is number two, and so on. The
function point
returns the current position of the cursor as a
number. Each buffer has its own value for point.
The mark is another position in the buffer; its value can be set
with a command such as C-SPC (set-mark-command
). If
a mark has been set, you can use the command C-x C-x
(exchange-point-and-mark
) to cause the cursor to jump to the mark
and set the mark to be the previous position of point. In addition, if
you set another mark, the position of the previous mark is saved in the
mark ring. Many mark positions can be saved this way. You can jump the
cursor to a saved mark by typing C-u C-SPC one or more
times.
The part of the buffer between point and mark is called the
region. Numerous commands work on the region, including
center-region
, count-lines-region
, kill-region
, and
print-region
.
The save-excursion
special form saves the locations of point and
mark and restores those positions after the code within the body of the
special form is evaluated by the Lisp interpreter. Thus, if point were
in the beginning of a piece of text and some code moved point to the end
of the buffer, the save-excursion
would put point back to where
it was before, after the expressions in the body of the function were
evaluated.
In Emacs, a function frequently moves point as part of its internal
workings even though a user would not expect this. For example,
count-lines-region
moves point. To prevent the user from being
bothered by jumps that are both unexpected and (from the user's point of
view) unnecessary, save-excursion
is often used to keep point and
mark in the location expected by the user. The use of
save-excursion
is good housekeeping.
To make sure the house stays clean, save-excursion
restores the
values of point and mark even if something goes wrong in the code inside
of it (or, to be more precise and to use the proper jargon, "in case of
abnormal exit"). This feature is very helpful.
In addition to recording the values of point and mark,
save-excursion
keeps track of the current buffer, and restores
it, too. This means you can write code that will change the buffer and
have save-excursion
switch you back to the original buffer. This
is how save-excursion
is used in append-to-buffer
.
(See section The Definition of append-to-buffer
.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
save-excursion
Expression
The template for code using save-excursion
is simple:
(save-excursion body...) |
The body of the function is one or more expressions that will be
evaluated in sequence by the Lisp interpreter. If there is more than
one expression in the body, the value of the last one will be returned
as the value of the save-excursion
function. The other
expressions in the body are evaluated only for their side effects; and
save-excursion
itself is used only for its side effect (which
is restoring the positions of point and mark).
In more detail, the template for a save-excursion
expression
looks like this:
(save-excursion first-expression-in-body second-expression-in-body third-expression-in-body ... last-expression-in-body) |
An expression, of course, may be a symbol on its own or a list.
In Emacs Lisp code, a save-excursion
expression often occurs
within the body of a let
expression. It looks like this:
(let varlist (save-excursion body...)) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the last few chapters we have introduced a fair number of functions and special forms. Here they are described in brief, along with a few similar functions that have not been mentioned yet.
eval-last-sexp
defun
For example:
(defun back-to-indentation () "Move point to first visible character on line." (interactive) (beginning-of-line 1) (skip-chars-forward " \t")) |
interactive
Common code characters are:
b
f
p
r
See section `Code Characters for `interactive'' in The GNU Emacs Lisp Reference Manual, for a complete list of code characters.
let
let
and give them an initial value, either nil
or a
specified value; then evaluate the rest of the expressions in the body
of the let
and return the value of the last one. Inside the
body of the let
, the Lisp interpreter does not see the values of
the variables of the same names that are bound outside of the
let
.
For example,
(let ((foo (buffer-name)) (bar (buffer-size))) (message "This buffer is %s and has %d characters." foo bar)) |
save-excursion
For example,
(message "We are %d characters into this buffer." (- (point) (save-excursion (goto-char (point-min)) (point)))) |
if
The if
special form is called a conditional. There are
other conditionals in Emacs Lisp, but if
is perhaps the most
commonly used.
For example,
(if (string-equal (number-to-string 21) (substring (emacs-version) 10 12)) (message "This is version 21 Emacs") (message "This is not version 21 Emacs")) |
equal
eq
equal
uses one meaning
of the word `same' and eq
uses another: equal
returns
true if the two objects have a similar structure and contents, such as
two copies of the same book. On the other hand, eq
, returns
true if both arguments are actually the same object.
<
>
<=
>=
<
function tests whether its first argument is smaller than
its second argument. A corresponding function, >
, tests whether
the first argument is greater than the second. Likewise, <=
tests whether the first argument is less than or equal to the second and
>=
tests whether the first argument is greater than or equal to
the second. In all cases, both arguments must be numbers or markers
(markers indicate positions in buffers).
string<
string-lessp
string=
string-equal
string-lessp
function tests whether its first argument is
smaller than the second argument. A shorter, alternative name for the
same function (a defalias
) is string<
.
The arguments to string-lessp
must be strings or symbols; the
ordering is lexicographic, so case is significant. The print names of
symbols are used instead of the symbols themselves.
An empty string, `""', a string with no characters in it, is smaller than any string of characters.
string-equal
provides the corresponding test for equality. Its
shorter, alternative name is string=
. There are no string test
functions that correspond to >, >=
, or <=
.
message
setq
set
setq
function sets the value of its first argument to the
value of the second argument. The first argument is automatically
quoted by setq
. It does the same for succeeding pairs of
arguments. Another function, set
, takes only two arguments and
evaluates both of them before setting the value returned by its first
argument to the value returned by its second argument.
buffer-name
buffer-file-name
current-buffer
other-buffer
other-buffer
as an argument and other than the current
buffer).
switch-to-buffer
set-buffer
buffer-size
point
point-min
point-max
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
fill-column
is greater than the argument passed to the function,
and if so, prints an appropriate message.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |