(replace-string "Bill" "Deb")
The function is not being called interactively in this case, so the interactive statement has no effect; the argument from is set to "Bill," and to is set to "Deb."
Getting back to our count-words-buffer command: it has no arguments, so its interactive command does not need a prompt string. The final modification we want to make to our command is to add a documentation string (or doc string for short), which is shown by online help facilities such as describe-function (C-h f). Doc strings are normal Lisp strings; they are optional and can be arbitrarily many lines long, although, by convention, the first line is a terse, complete sentence summarizing the command's functionality. Remember that any double quotes inside a string need to be preceded by backslashes.
With all of the fixes taken into account, the complete function looks like this:
(defun count-words-buffer ( )
"Count the number of words in the current buffer;
print a message in the minibuffer with the result."
(interactive)
(save-excursion
(let ((count 0))
(goto-char (point-min))
(while (< (point) (point-max))
(forward-word 1)
(setq count (1+ count)))
(message "buffer contains %d words." count))))
11.2 Lisp Primitive Functions
Now that you've seen how to write a working command, we'll discuss Lisp's primitive functions. These are the building blocks from which you'll build your functions. As mentioned above, Lisp uses functions where other languages would use operators, that is, for arithmetic, comparison, and logic. Table 11-3 shows some Lisp primitive functions that are equivalent to these operators.
Table 11-3. Lisp primitive functions
| Arithmetic | +, -, *, / |
% (remainder) |
|
1+ (increment) |
|
1- (decrement) |
|
max, min |
|
| Comparison | >, <, >=, <= |
/= (not equal) |
|
= (for numbers and characters) |
|
equal (for strings and other complex objects) |
|
| Logic | and, or, not |
All the arithmetic functions except 1+, 1-, and % can take arbitrarily many arguments, as can and and or. An arithmetic function returns floating point values only if at least one argument is a floating point number, so for example, (/ 7.0 4) returns 1.75, and (/ 7 4) returns 1. Notice that integer division truncates the remainder.
It may seem inefficient or syntactically ugly to use functions for everything. However, one of the main merits of Lisp is that the core of the language is small and easy to interpret efficiently. In addition, the syntax is not as much of a problem if you have support tools such as Emacs's Lisp modes to help you.
11.2.1 Statement Blocks
We have seen that a statement block can be defined using the let function. We also saw that while and save-excursion include statement blocks. Other important constructs also define statement blocks: progn and other forms of let.
progn, the most basic, has the form:
(progn
statement-block)
progn is a simple way of making a block of statements look like a single one, somewhat like the curly braces of Java or the begin and end of Pascal. The value returned by progn is the value returned by the last statement in the block. progn is especially useful with control structures like if (see the following discussion) that, unlike while, do not include statement blocks.
The let function has other forms as well. The simplest is:
(let (var1 var2 ...)
statement-block)
In this case, instead of a list of (var value) pairs, there is simply a list of variable names. As with the other form of let, these become local variables accessible in the statement block. However, instead of initializing them to given values, they are all just initialized to nil. You can actually mix both forms within the same let statement, for example:
(let (var1 (var2 value2) var3 ...)
statement-block)
In the form of let we saw first, the initial values for the local variables can be function calls (remember that all functions return values). All such functions are evaluated before any values are assigned to variables. However, there may be cases in which you want the values of some local variables to be available for computing the values of others. This is where let*, the final version of let, comes in. let* steps through its assignments in order, assigning each local variable a value before moving on to the next.
For example, let's say we want to write a function goto-percent that allows you to go to a place in the current buffer expressed as a percentage of the text in the buffer. Here is one way to write this function:
(defun goto-percent (pct)
(interactive "nGoto percent: ")
(let* ((size (point-max))
(charpos (/ (* size pct) 100)))
(goto-char charpos)))
As we saw earlier, the interactive function is used to prompt users for values of arguments. In this case, it prompts for the integer value of the argument pct. Then the let* function initializes size to the size of the buffer in characters, then uses that value to compute the character position charpos that is pct (percent) of the buffer's size. Finally, the call of goto-char causes point to be moved to that character position in the current window.