Emacs Lisp Basics

Advertise Here

, 2005-10, …, 2011-05-17

This page is a short, practical, tutorial of Emacs Lisp the language.

To evaluate a elisp code, type a elisp code in a blank file. For example, type (+ 3 4), then move your cursor after the closing parenthesis, then type 【Ctrl+x Ctrl+e】 (eval-last-sexp). Emacs will evaluate the lisp expression to the left of the cursor. Alternatively, you can select the lisp code, then call eval-region.

Alternatively, you can call ielm. It will start a interactive elisp command line interface.

To find the inline documentation of a function, call describe-functionCtrl+h f】.

Printing

; printing
(message "hi")

; printing variable values
(message "Her age is: %d" 16)        ; %d is for number
(message "Her name is: %s" "Vicky")  ; %s is for string
(message "Her mid init is: %c" 86)   ; %c is for character in ASCII code
(message "My list is: %S" '(8 2 3))  ; %S is for a list

You can see the output in the buffer named “*Messages*”. You can switch to it by 【Ctrl+h e】 (view-echo-area-messages).

See also: Emacs Lisp's print, princ, prin1, format, message.

Arithmetic Functions

(+ 4 5 1)     ;    ⇒ 10
(- 9 2)       ;    ⇒  7
(- 9 2 3)     ;    ⇒  4
(* 2 3)       ;    ⇒  6
(* 2 3 2)     ;    ⇒ 12
(/ 7 2)       ;    ⇒  3 (Integer part of quotient)
(/ 7 2.0)     ;    ⇒  3.5
(% 7 4)       ;    ⇒  3 (Remainder)
(expt 2 3)    ;    ⇒ 8

WARNING: When you need to input a decimal number, you need to include a zero after the dot, like this: “2.0”. A number without “0” after the dot is still integer. So, for example, (/ 7 2.) returns 3, not 3.5.

;; float must have a dot followed by a zero
(integerp 3.) ; returns t
(floatp 3.) ; returns nil
(floatp 3.0) ; returns t

Function names that ends with a “p” often means it returns either true or false. (The “p” stands for “predicate”) t means true; nil means false.

Converting String and Numbers

(string-to-number "3")
(number-to-string 3)

(info "(elisp) Numbers")

True and False

In elisp, the symbol nil is false, anything else is considered true. So, 0 is true, and empty string "" is also true. Also, nil is a synonym for the empty list (), so () is also false.

; all the following are false. They all evaluate to “nil”
(if nil "yes" "no") ; ⇒ "no"
(if () "yes" "no") ; ⇒ "no"
(if '() "yes" "no") ; ⇒ "no"
(if (list) "yes" "no") ; ⇒ "no", because (list) is a empty list, same as ()

By convention, the symbol t is used for true.

(if t "yes" "no") ; ⇒ "yes"
(if 0 "yes" "no") ; ⇒ "yes"
(if "" "yes" "no") ; ⇒ "yes"
(if [] "yes" "no") ; ⇒ "yes". The [] is vector of 0 elements

(and t nil) ; ⇒ nil
(or t nil) ; ⇒ t

There is no “boolean datatype” in elisp. Just remember that nil and empty list () are false, anything else is true.

Comparison Functions

Comparing numbers:

(< 3 4) ; less than
(> 3 4) ; greater than
(<= 3 4) ; less or equal to
(>= 3 4) ; greater or equal to

(= 3 3)   ; ⇒ t
(= 3 3.0) ; ⇒ t

(/= 3 4) ; ⇒ t

Comparing strings:

(string-equal "this" "this") ; ⇒ t. Case matters.

To test if two symbols have the same datatype and value, use equal.

;; testing if two values have the same datatype and value.
(equal "abc" "abc") ; ⇒ t
(equal 3 3) ; ⇒ t
(equal 3.0 3.0) ; ⇒ t
(equal 3 3.0) ; ⇒ nil. Because datatype doesn't match.

;; testing equality of lists
(equal '(3 4 5) '(3 4 5))  ; ⇒ t
(equal '(3 4 5) '(3 4 "5")) ; ⇒ nil

;; testing equality of symbols
(equal 'abc 'abc) ; ⇒ t

There's also the function eq, but don't use it unless you know what you are doing.

To test for inequality, the /= is for numbers only, and doesn't work for strings and other lisp data. Use not to negate your equality test, like this:

(not (= 3 4)) ; ⇒ t
(/= 3 4) ; ⇒ t. “/=” is for comparing numbers only

(not (equal 3 4)) ; ⇒ t. General way to test inequality.

(info "(elisp) Comparison of Numbers")(info "(elisp) Equality Predicates")

Global and Local Variables

setq is used to set variables. Variables need not be declared, and is global.

(setq x 1) ; assign 1 to x
(setq a 3 b 2 c 7) ; assign 3 to a, 2 to b, 7 to c

To define local variables, use let. The form is: (let (‹var1› ‹var2› …) ‹body›) where ‹body› is (one or more) lisp expressions. The body's last expression's value is returned.

(let (a b)
 (setq a 3)
 (setq b 4)
 (+ a b)
) ; returns 7

Another form of let is this: (let ((‹var1› ‹val1›) (‹var2› ‹val2›) …) ‹body›). Example:

(let ((a 3) (b 4))
 (+ a b)
) ; returns 7

This form lets you set values to variable without using many setq in the body. This form is convenient if you just have a few simple local vars with known values.

(info "(elisp) Variables")

A Block of Expressions

Sometimes you need to group several expressions together. This can be done with progn. For example, this code:

(progn (message "hi") (message "lo"))

is equivalent to

(message "hi") (message "lo")

The purpose of (progn …) is similar to a block of code {…} in C-like languages. It is used to group together a bunch of expressions into one single parenthesized expression. For example, like this:

(if something
    (progn ; true
    …
    )
    (progn ; else
    …
    )
)

(info "(elisp) Sequencing")

If Then Else

The form for if statement is: (if ‹test› ‹body›).

If you want a “else” part, the form is (if ‹test› ‹true body› ‹false body›).

Examples:

(if (< 3 2) (message "yes") )
(if (< 3 2) (message "yes") (message "no") )

(if nil (message "yes") (message "no") )  ; prints no

(info "(elisp) Control Structures")

If you do not need a “else” part, it is prefered that you use the function when instead. The form is this: (when ‹test› ‹expr1› ‹expr2› …). Its meaning is the same as (if ‹test› (progn ‹expr1› ‹expr2› …)).

Iteration

The following code shows a loop using the while function. The form is: (while ‹test› …).

(setq x 0)

(while (< x 4)
  (print (format "yay %d" x))
  (setq x (1+ x)))

(info "(elisp) Iteration")

In the following sample code, it inserts Unicode chars 32 to 126. First, it sets a local variable x to 32. Then it starts a while loop, insert the corresponding Unicode char, then increase x by 1.

(let ((x 32))
  (while (< x 127)
    (ucs-insert x)
    (setq x (+ x 1))))

Note: There is no “for” loop construct.

Sequence, List, Vector, Array

See: Emacs Lisp Tutorial: List & Vector.

Defining a Function

Basic function definition is of the form: (defun ‹function name› (‹param1› ‹param2› …) "‹doc string›" ‹body›) . Example:

(defun myFunction () "testing" (message "Yay!") )

This function can be called in other places in a elisp program but the function won't be available when user types 【Alt+x】. To make a function available for interactive use, add the (interactive) right after the doc string.

The following is a basic function definition for interactive use. The function takes no argument. Evaluate the following code. Then, you can call it by 【Alt+x yay】

(defun yay ()
  "Insert “Yay” at cursor position."
  (interactive)
  (insert "Yay!"))

The following is a basic function definition, taking one argument from 【Ctrl+u】. You can call it by typing 【Ctrl+u 7 Alt+x myFunction】.

(defun myFunction (myArg)
  "Prints the argument"
  (interactive "p")
  (message "Your argument is: %d" myArg)
)

The following is a basic function definition taking region as arg. Note the (interactive "r"). The "r" is a code that tells emacs that the function will receive the buffer's region as its argument.

(defun myFunction (myStart myEnd)
  "Prints region start and end positions"
  (interactive "r")
  (message "Region begin at: %d, end at: %d" myStart myEnd)
)

In summary, the (interactive) clause makes your function into a command that can be called by 【Alt+x】. A function with the (interactive) clause is called a command. The (interactive ‹x›) form takes a single-letter code x to indicate how the command gets its arguments from user. There are about 30 codes for the x, but the most useful are the following:

Here is a function definition template that almost all elisp commands follow:

(defun myCommand ()
  "One sentence summary of what this command do.

More detailed documentation here."
  (interactive)
  (let (localVar1 localVar2 …)
    ; do something here …
    ;     ; last expression is returned
  )
)

When a function is called, the last expression in the function's definition body is returned. (You do not have to write “return …” as in other languages.)

See also: Emacs Lisp Functions Optional ParametersEmacs Function's Inline Doc String Markups.

(info "(elisp) Defining Functions")(info "(elisp) Defining Commands")

The Concept of Symbols in Lisp

LISP differs from most programing languages such as C, Java, Perl, Python, in that it deals with symbols, as opposed to just variables and values.

In practice, this means that in lisp, variables can be manipulated in its un-evaluated state. The situation is like the need for the “evaluate” command in many languages, where the programer can built code as strings and do evaluate(myCodeString) to achieve meta-programing. In lisp, variable's unevaluated form are always available. You just put a apostrophe in front of it. This is why lisp refers to variable or function as “symbols”. This makes meta-programing more powerful.

For example, in most languages, once you defined x=3, you cannot manipulate the variable “x” because it gets evaluated to 3 right away. If you want, you have to build a string "x" and manipulate this string, then finally use something like evaluate(myCodeString) to achieve the effect. In most languages, the use of evaluate() breaks down quickly because the language is not designed for doing it. It's slow, difficult to debug, and there lacks many facilities for such meta programing.

The ability to meta-program has many applications. For example, when you need to take user input as code (such as math formulas), or need to manipulate math expressions, or writing programs that modify itself at run-time.

blog comments powered by Disqus