Sams Teach Yourself Emacs in 24 Hours

ContentsIndex

Hour 22: Learning Lisp Basics

Previous HourNext Hour

Sections in this Hour:

 

Values in Lisp


Several different values, of course, exist in Lisp. These values are now explained using a real-life example where a need for such values exists.

Booleans

In many situations there are two possible values for a given configuration option. The option can often be stated as a yes/no question. An example might be: "Do you want a blank line inserted if you ask Emacs to move point to the next line, when you already are located at the last line of the buffer?" The value to an answer of the preceding question is a truth value, either true or false (true represents the answer yes, and false represents no, in the given example).

The value true is in Lisp represented using the character t, and false is represented using nil. The reason for this strange convention is merely one of historical reasons. Thus telling Emacs that it should insert a blank line is done using the line


(setq next-line-add-newlines t)

whereas telling Emacs not to insert a blank line is done by inserting the line


(setq next-line-add-newlines nil)

Numbers

Numbers are also a value type needed in Emacs. Examples of the use of numbers include the number of backups to keep, the number of characters to indent when programming C, and the maximum size of buffers to fontify with font-lock mode. Numbers are specified as is.

String

Strings are used in Emacs in many different situations. Most of these situations are when programming Lisp. Examples of these might be a string of text to search for, a message sent to the user, and names of different things such as buffers, files, and bookmarks. When customizing things in your .emacs file, you often use strings for directory or filenames and regular expressions. String are represented by placing quotation marks around the string. An example is


(setq abbrev-file-name "/home/blackie/Abbreviations")

Note - If the string contains a backslash, you need to escape it. Thus the regular expression that matches the word ".Emacs" (that is, a period, the letter E, and so on) looks like "\.Emacs" (the period needs to be escaped otherwise it would mean any single character). To insert this regular expression into a string, you need to escape the backslash, and the result is thus "\\.Emacs".

Symbols

In Emacs, a data type called symbols exists. The difference between a symbol and a string is too technical if you are not a programmer, so in this case you might think about symbols as another way of writing a string.

Symbols are written by putting a single quotation mark in front of the name as in 'do-backup.

Note - If you are a programmer, this is the difference between a symbol and a string. A symbol is an object that can be compared to another object in constant time. Emacs can, for example, answer whether 'aaaaab is equal to 'aaaaac in constant time. On the other hand for Emacs to compare the strings "aaaab" and "aaaaac", it needs to compare the first character and, if these are the same, it must compare the second character, and so on. Thus the time it takes to compare two strings is equal to the length of the strings.

Lists

You often need to list a number of values. Examples of this include

Lists are specified by listing each of the elements within a pair of parentheses, the outermost list must be prefixed with a quote, as discussed later in this hour. The following are examples of lists:


1. (setq tab-stop-list '(2 4 6 8 10 12 14 16 18 20)) 
2. (setq template-default-directories 
       '("~/Templates" "/usr/local/Templates")) 
3. (setq nnmail-split-methods '( 
       ("debian-devel" "^To:.*debian-devel@lists.debian.org") 
       ("postcard" "^Subject:.*Postcard:") 
       ("Miscellaneous" ""))) 

The first example is a list of numbers, and the second is a list of strings. The third example is a list of lists. Each of these lists contain two elements that are strings.

The list must be prefixed with a quote, otherwise the Lisp interpreter thinks that the first element of the list is a function for it to execute, and the rest of the elements are arguments to the function. Thus if you write


(setq a (+ 1 2))

then the Lisp interpreter assigns the value 3 to the variable a. If, on the other hand, you write


(setq a '(+ 1 2))

the list with three elements, namely the symbol + as the first element, 1 as the second, and 2 as the third, is assigned to the variable.

Association Lists (alist)

An association list is a map from a key to a value. An example of this data type is auto-mode-alist, which is a variable that describes which major mode to start based on the filename. A regular expression describing properties for the filename is the key, whereas the name of the major-mode is the value. A key/value pair is listed like a list, with the exception that a period is inserted in between. This can be seen from the following example:


(setq auto-mode-alist '( 
  ("\\.gnus$" . emacs-lisp-mode) 
  ("\\.py$" . python-mode) 
  ("\\.c\\'" . c-mode) 
  ("\\.h\\'" . c-mode) 
  ("[Mm]akefile"  . makefile-mode) 
)) 

To be completely accurate, the preceding code is a list, in which each individual element is itself a list (although it is a special kind of list).

Operations on Lists

Often you do not want to create a new list, but rather modify an existing one. An example of this is the list of directories where Emacs searches for Lisp files. You do not want to replace the existing list of directories whenever you have an additional directory for Emacs to look in. Instead you want to tell Emacs to look in the directories it is used to and your new directory.

Whether your new element should be added to the front of the list or the end of the list depends on what your intentions are. In the example, adding the directory to the front of the list means that Lisp files in your new directory take precedence over the others. That is, if a Lisp file exists both in your new directory and in one of the directories from the original set of directories, Emacs uses the one from your new directory. Likewise, if you add your directory to the end of the list, a file from your directory only is used, if it is in none of the other directories.

Inserting in the Front of a List

Adding an element to the front of the list is done using the function cons. This function takes an element to add and a list, and returns a new list as a result. Thus, to add the directory called ~/Lisp-files, you should insert the following into your .emacs file:


(setq load-path (cons "~/Lisp-files" load-path))

The code says that the string ~/Lisp-files should be inserted at the front of the list contained in the variable load-path. The result should be inserted into the variable load-path again. (This way the variable load-path is updated.) The parenthesis in front of the word cons tells Lisp that cons is a function it should execute. This is discussed later.

To insert two elements in front of the variable load-path, you can write something like:


(setq load-path 
   (cons "~/Lisp-files/Major-modes" 
       (cons "~/Lisp-files/Minor-modes" load-path))) 

To read the previous example, you must read from the inside out. First the string ~/Lisp-files/Minor-modes is inserted in the front of the list from the variable load-path. This results in a new list. Next the string ~/Lisp-files/Major-modes is inserted in the front of the just-made list, and this new list is finally inserted into the variable load-path.

Inserting at the End of a List

Inserting elements at the end of the list is done by forming a list and appending this newly formed list to the end of the original list. Thus you do not insert an element to the end of a list.

Note - Lists are implemented by having a pointer to the front of the list. Adding an element to the front of the list is done in constant time, but inserting an element to the end of a list takes time equal to the length of the list. Forcing you to append a list of elements to a list rather than simply insert at the end several times makes you aware of the time it takes.


Thus to insert the two directories to the end of the list, insert the following into your .emacs file:


(setq load-path (append load-path '("~/Lisp-files/Major-modes" 
                                    "~/Lisp-files/Minor-modes"))) 

Sams Teach Yourself Emacs in 24 Hours

ContentsIndex

Hour 22: Learning Lisp Basics

Previous HourNext Hour

Sections in this Hour: