Emacs Lisp Basics

By Xah Lee. Date: . Last updated: .

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

To evaluate elisp code, for example, type (+ 3 4), then move your cursor to after the closing parenthesis, then call eval-last-sexpCtrl+x Ctrl+e】. Emacs will evaluate the lisp expression to the left of the cursor.

Or, you can select the lisp code, then Alt+x eval-region.

To find the doc string of a function, Alt+x describe-functionCtrl+h f】. (if the function name is under cursor, you don't need to type the name, just hit Enter.)

emacs lisp eval 2017 01 04
eval emacs lisp code basics. [see Evaluate Emacs Lisp Code]

To turn on syntax highlight, Alt+x emacs-lisp-mode.


; 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 "My list is: %S" (list 8 2 3))  ; %S is for any lisp expression

You can see the output in the buffer named “*Messages*”. You can switch to it by Alt+x view-echo-area-messagesCtrl+h e】.

[see Elisp: Print, Output]

[see Elisp: Format String]


(+ 4 5 1)  ; 10
(- 9 2)    ; 7
(- 9 2 3)  ; 4
(* 2 3)    ; 6
(* 2 3 2)  ; 12

;; integer part of quotient
(/ 7 2)    ; 3

;; division
(/ 7 2.0)  ; 3.5

;; mod, remainder
(% 7 4)    ; 3

;; power; exponential
(expt 2 3) ; 8

WARNING: single digit decimal number such as 2. needs a zero after the dot, like this: 2.0. For example, (/ 7 2.) returns 3, not 3.5.

;; 3. is a integer, 3.0 is a float
(integerp 3.) ;  t
(floatp 3.) ;  nil
(floatp 3.0) ;  t

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

Convert Float/Integer

;; int to float
(float 3) ; 3.0

(truncate 3.3) ; 3

(floor 3.3) ; 3

(ceiling 3.3) ; 4

(round 3.4) ; 3

(info "(elisp) Numeric Conversions")

Convert String and Number

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

You can also use format to convert number to string. [see Elisp: Format String]

(info "(elisp) Numbers")

True, False

In elisp, the symbol nil is false, anything else is true. Also, nil is equivalent to 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) eval to 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

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

Boolean Functions

Here's and and or.

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

;; can take multiple args
(and t nil t t t t) ;  nil

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.00000000000000001) ;  t

(/= 3 4) ; not equal. ⇒ t

Comparing strings:

;; compare string
(equal "abc" "abc") ;  t

;; dedicated function for comparing string
(string-equal "abc" "abc") ;  t

(string-equal "abc" "Abc") ;  nil. Case matters

;; can be used to compare string and symbol
(string-equal "abc" 'abc) ;  t

For generic equality test, use equal. It tests if two values have the same datatype and value.

;; test if two values have the same datatype and value.

(equal 3 3) ;  t
(equal 3.0 3.0) ;  t

(equal 3 3.0) ;  nil. Because datatype doesn't match.

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

;; test equality of strings
(equal "e" "e") ;  t

;; test equality of symbols
(equal 'abc 'abc) ;  t

There's also the function eq, it returns t if the two args are the same Lisp object. This is usually not what you want. (eq "e" "e") returns nil.

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.

even, odd

(= (% n 2) 0) ; test even

(= (% n 2) 1) ; test odd


Global 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) ; multiple assignment

Local Variables

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)
) ;  7

Another form of let is this:

(let ((var1 val1) (var2 val2) …) body)

(let ((a 3) (b 4))
 (+ a b)
) ;  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")

If Then Else

The form for “if” expression is:

(if test body)


(if test true_body false_body)

(if (< 3 2) 7 8 ) ; 8

;; no false expression, return nil
(if (< 3 2) (message "yes") ) ; nil

(info "(elisp) Control Structures")

If you do not need a “else” part, you should use the function when instead, because it is more clear. The form is:

(when test expr1 expr2 )

Its meaning is the same as

(if test (progn expr1 expr2 ))

Block of Expressions

Sometimes you need to group several expressions together as one single expression. This can be done with progn.

(progn (message "a") (message "b"))
;; is equivalent to
(message "a") (message "b")

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. Most of the time it's used inside “if”.

(if something
    (progn ; true
    (progn ; else

progn returns the last expression in its body.

(progn 3 4 ) ; 4

(info "(elisp) Sequencing")


Most basic loop in elisp is with while.

(while test body)

, where body is one or more lisp expressions.

(setq x 0)

(while (< x 4)
  (print (format "number is %d" x))
  (setq x (1+ x)))
;; inserts Unicode chars 32 to 126
(let ((x 32))
  (while (< x 127)
    (insert-char x)
    (setq x (+ x 1))))

Usually it's better to use dolist or dotimes.

[see Elisp: Map List/Vector]

(info "(elisp) Iteration")

Break/Exit a Loop

Elisp: throw, catch

Sequence, List, Vector

Elisp: Sequence Type

Elisp: Vector

Elisp: List

Define a Function

Basic function definition is of the form:

(defun function_name (param1 param2 ) doc_string body)

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

When a function is called, the last expression in the function's definition body is returned. (there's no “return statement”.)

(info "(elisp) Defining Functions")

Define a Command

A command is a function that emacs user can call by execute-extended-commandAlt+x】.

When a function is also a command, we say that the function is available for interactive use.

To make a function available for interactive use, add (interactive) right after the doc string.

Evaluate the following code. Then, you can call it by execute-extended-commandAlt+x

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

(info "(elisp) Defining Commands")

Here is a function definition template that majority of elisp commands follow:

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

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

See also:

Put $5 at https://www.patreon.com/xahlee , or goto paypal.com and pay to Xah@XahLee.org . Message me on XahLee discord, say so, ask me questions.
Or Buy Xah Emacs Tutorial

Emacs Tutorial

Emacs Init

Emacs Keys


ELisp Examples

ELisp Write Major Mode



Basic Functions

Writing Command

Writing Script

Lisp Data Structure

Lisp Symbol

Elisp Misc