HomeMathComputingArtsWordsLiteratureMusictwitter facebook webfeed

Emacs Lisp Basics

Advertise Here For Profit

Xah Lee, 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, type 【Ctrl+h f】 (describe-function).

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 0 followed by a dot
(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.

(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”
nil
()
'()
(list)
(if nil "yes" "no") ; ⇒ "no"
(if () "yes" "no") ; ⇒ "no"
(if '() "yes" "no") ; ⇒ "no"
(if (list) "yes" "no") ; ⇒ "no"

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 () is 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= "this" "this") ; ⇒ t. Case matters.
(string< "a" "b") ; ⇒ t. by lexicographic order.
(string< "B" "b") ; ⇒ t.

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

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)
  (princ (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 functions use:

(defun myFunction (arg1 arg2 …)
  "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 Parameters.

(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, 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