Common Lisp

語法

Common Lisp是Lisp編程語族的一種方言; 它使用S-表達式來表示源碼和資料結構。函數呼叫、宏形式和基本形式都以列表來編寫，列表的第一項是函數名稱，如以下範例：
 (+ 2 2)   ; 将 2 加上2 得 4。函數名稱為'+'，在Lisp語法中是唯一的(只能作用於數值)。
 (defvar *x*)      ; 先確保 *x* 變量存在，尚未賦值給它。星號也是變量名稱的一部份，
                   ; 依慣例約定表示一個特殊（全局）變量。符號 *x* 與生俱有的屬性是
                   ; 對於它後續的綁定是動態可變的，而非詞法靜止不變的。
 (setf *x* 42.1)   ; 對 *x* 變量賦予浮點數值 42.1。
 ;; 定义计算一个数的平方函数：
 (defun square (x)
               (* x x))
 ;; 执行这个函数：
 (square 3)        ; 返回平方值 9
 ;; 'let'構造為區域變量創建一個作用域。這裡變量'a' 被綁定到 6，變量'b'被綁定到 4。&nbsp;;; 'let'的內部是一個函式體，對它求值後會返回最後一個計算值。這個'let'表達式將
 ;; a 和 b 相加的結果返回。變量 a 和 b 只存在於詞法作用域中，除非它們已先被標記&nbsp;;; 成特殊變量（例如上述的 DEFVAR）。
 (let ((a 6)
       (b 4))
   (+ a b))        ; 返回數值 10

資料型別

Common Lisp 擁有豐富的資料型別。

純量型別

數值型別包括整數，分數，浮點數和複數。Common Lisp使用大數（bignums）來表示任意大小和精度的數值。
分數型別確切地代表分數，很多語言並不具備這種能力。Common Lisp會自動將數值轉換成適當的型別。有許多方式取捨數值，函數round將參數四捨六入為最接近的整數，逢五則取偶整數。truncate，floor和ceiling分別朝向零，向下或向上取整數。所有這些函數將捨去的小數當作次要值返回。
例如，（floor -2.5）產生 -3, 0.5；（ceiling -2.5）產生 -2，-0.5；（round 2.5）得到 2,0.5；和（round 3.5）得到 4，-0.5。
Common Lisp字元型別不限於ASCII字符，因為在ASCII出現前Lisp就已經存在了。大多數現代實現允許Unicode字元。
符號（Symbol）型別是Lisp語言共有的，而在其它語言中較少見。一個符號是個命名唯一的資料物件，它擁有幾個部份：名稱，值，函數，屬性列表（property list）和套件。其中，值單元和函數單元是最重要的。Lisp中的符號通常類似於其它語言中的標識符（identifier）用法：保存變量的值；然而還有很多種用途。一般來說，對一個符號求值時會得到以該符號為變量名稱的值，但也有例外：譬如在關鍵符套件中的符號，形如:foo的符號值就是它本身（自我評估的，self-evaluating），而符號T和NIL則用於表示布爾邏輯值真與假。Common Lisp可設計容納符號的命名空間，稱為「套件」（package）。

資料結構

Common Lisp的序列型別包括列表、向量、位元向量和字串。有許多函式可對應不同型別的序列進行操作。
CL如同所有Lisp方言，列表由點對（conses）組成，有時稱為cons單元、序偶或構對。一個點對是帶有兩個儲存槽的資料結構，分別稱為car和cdr。列表就是一條點對的串列，或只是空列表。每一個點對的CAR會參照列表的成員（可能是另一個列表）。而除了最後一個的CDR參照到nil值之外，其餘的CDR都會參照下一個點對。Conses也能輕易地實現樹和其它複雜的資料結構；儘管一般建議以結構體或是類別的實例來代替。利用點對能夠創建循環形的資料結構。
CL支援多維陣列，且如需要能動態地調整陣列大小。多維陣列常用於數學中的矩陣運算。向量就是一維陣列。陣列可載入任何型別（甚至於混合的型別）的成員，或只專用於特定某一型別的成員，例如由整數構成的位元向量。許多Lisp實作會根據特定型別，對陣列的操作函數進行優化。兩種特定型別的專用陣列是內建的：字串和位元向量。字串是由許多字元構成的向量，而位元向量是由許多位元構成的向量。
雜湊表儲存資料物件之間的關聯，任何物件都可以作為雜湊表的鍵或值。和陣列一樣，雜湊表可依需求自動調整其大小。
套件是一組符號的集合，主要用於將程序的個別部份區分命名空間。套件能匯出一些符號，將它們作為共用介面的某一部份，也可以匯入其它套件引用並概括承受其中的符號。
CL的結構體（Structures）類似於C語言的structs和Pascal的records，是一種任由使用者發揮的複雜資料結構定義，表示具有任意數量和任何型別的欄位（也叫做槽）。結構允許單一繼承。
類別（Class）在後期被整合進Common Lisp中，有些概念與結構體重疊，但類別提供了更多的動態特性和多重繼承（見 CLOS）。由類別創建的物件稱為實例。有個特殊情況是泛型（Generics）的雙重角色，泛型既是函數，也是類別的實例物件。

定義函數

宏defun用來定義函數。函數定義給出了函數名，參數名和函數體：
(defun square(x)
   (* x x))
函數定義中可以包括「聲明」，它可以指示編譯器優化設置或參數的數據類型等。還可以在函數定義中包括「文檔字符串」（docstring），Lisp系統用它們形成互動式文檔：
(defun square(x)
   (declare (number x) (optimize (speed 3) (debug 0) (safety 1)))
   "Calculates the square of the number x."
   (* x x))
匿名函數用lambda表達式定義。Lisp編程頻繁使用高階函數，以匿名函數作為其參數的作法十分有效。
還有一些有關於函數定義和函數操作的運算符。如，操作符compile可以用來重新編譯函數。（一些Lisp系統默認下在解釋器里運行函數，除非指示編譯它；其他Lisp系統在函數輸入時即被編譯。）

定義泛型函數及方法

defgeneric宏用來定義泛型函數，而defmethod宏則用來定義方法。泛型函數是一些方法的集合。方法可依照CLOS標準類別、系統類別、結構類別或物件，以特定方式處理它們所使用的參數。許多型別都有相對應的系統類別。當呼叫泛型函數時，多樣派發（multiple-dispatch）將會依型別確定要應用的有效方法。如下列範例展示了對不同型別的參數如數值、向量或字串，設計對應的add方法將兩個物件相加的動作。
 (defgeneric add (a b))
 (defmethod add ((a number) (b number))
    (+ a b))
 (defmethod add ((a vector) (b number))
    (map 'vector (lambda (n) (+ n b)) a))
 (defmethod add ((a vector) (b vector))
    (map 'vector #'+ a b))
(defmethod add ((a string) (b string))
  (concatenate 'string a b) )
 (add 2 3)                   ; returns 5
 (add #(1 2 3 4) 7)          ; returns #(8 9 10 11)
 (add #(1 2 3 4) #(4 3 2 1)) ; returns #(5 5 5 5)
 (add "COMMON " "LISP")      ; returns "COMMON LISP"
泛型函數也是第一類資料型別。除了上面陳述之外，泛型函數和方法還有更多的特性。

函數名字空間

函數的名字空間與數據變量的名字空間是分離的。這是Common Lisp和Scheme程式語言的一個重要不同之處。在函數名字空間定義名字的操作符包括defun,flet，和labels。
要用函數名把函數作為參數傳給另一個函數，必須使用function特殊操作符，通常簡略為#'。上文第一個sort的例子中，為了引用在函數名字空間名為>的函數，使用了代碼#'>。
Scheme程式語言的求值模型更簡單些：因為只有一個名字空間，式（form）中所有位置都被求值（以任意順序）-- 不僅是參數。所以以一種方言（dialect）寫就的代碼往往令熟悉其它方言程式設計師感到迷惑。例如，許多CL程式設計師喜歡使用描述性的變量名如"list"或"string"，在Scheme中這將導致問題，因為它們可能局部覆蓋了函數名字。
為函數提供分離的名字空間是否有益是Lisp社區不斷爭論的主題之一，常被稱為「Lisp-1與Lisp-2辯論」。這些名稱出現於Richard P. Gabriel和Kent Pitman 1998年的一篇論文，其中廣泛的比較了這兩種方法。

作用域

與許多其它編程語言中的程式一樣，Common Lisp編程使用名稱來引用變量、函數和許多其它類型的實體。被命名的參照只在其作用域中有用。名稱與引用實體之間的關聯稱為綁定。作用域是指確定名稱具有特殊綁定的情況。

全局

Lisp中的一些環境總是存在於全局作用域之中， 例如定義了一個新型別，那麼以後在任何地方都會知道它。

該類型別的參照會從全局作用域中的環境去尋找。

動態

環境在Common Lisp中有一種類型是動態環境。在這種環境中建立的綁定具有動態的作用域，這表示某些構造例如let，會在執行的起點就先建立綁定，而在該構造完成執行時消失：它的生命週期依附著這區塊動態地觸發和停用。然而動態綁定不僅在該區塊中可見；對於從該區塊中調用的所有函數也是可見的。這樣的可見性被稱為不定的作用域。具有動態（依附區塊的觸發和停用相關的生命週期）和不定作用域（從該區塊調用的所有函數可見）的綁定，被稱為具有動態作用域。
Common Lisp支援動態作用域的變量，也稱為特殊變量。有些其它類型的綁定也必須是動態作用域的，例如重新啟動和捕獲標籤。函數綁定不能以flet（僅提供詞法範圍的函數綁定）進行動態作用域，但可以將函數物件（Common Lisp中的第一類物件）分配給動態作用域的變量，在動態作用域內使用let綁定，然後再以funcall或APPLY調用。
動態作用域非常有用，因為它將參照的清晰度和規律添加到全局變量中。計算機科學中的全局變量被認為是潛在的錯誤來源，因為它們可能導致模組之間存有特殊隱蔽的溝通渠道，從而導致令人驚訝而不在預期中的交互作用。
在Common Lisp中，只有頂層綁定的特殊變量就像其它編程語言中的全局變量一樣。它可以儲存一個新的值，該值僅替換頂層綁定中的值。造成使用全局變量的核心錯誤，是粗心的替代了全局變量值。但是，使用特殊變量的另一種方法是，在表達式中給它一個新的區域綁定。這有時被稱為「重新綁定」變量。動態作用域中對變量的綁定，會創建一個臨時的新記憶體位置給予該變量，並將該名稱與該位置相關聯。當該綁定有效，對該變量的所有參照都指向新的綁定；之前的綁定則是被隱藏起來的。當綁定表達式的執行結束時，臨時的記憶體位置消失，而舊綁定浮現出來，變量的原始值依舊完好無損。當然，同一變量的多個動態綁定可以嵌套。
在支援多緒的Common Lisp實作中，動態作用域是針對每個執行緒的。因此，特殊變量是當成執行緒區域存儲的抽象化。如果一個執行緒重新綁定了特殊變量，則此重新綁定對其它執行緒中的該變量沒有作用。儲存在綁定中的值只能由創建該綁定的執行緒取得。如果每個執行緒綁定一些特殊變量*x*，則*x*的行為就像執行緒在本地中儲存一樣。在沒有重新綁定*x*的執行緒中，它的行為就像一個普通的全局變量：所有這些執行緒的參照都會指向*x*的頂層綁定。
動態變量可以用來擴展執行上下文，並附加上下文訊息，這些信息在函數之間隱含地傳遞，而不必顯示為額外的函數參數。當執行控制的轉移必須穿過不相關的代碼層時，不能藉由額外參數來擴展傳遞附加數據，所以這是非常有用的。這樣的情況通常需要一個全局變量，必須能夠被儲存和恢復，以便在遞歸時不會中斷：動態變量的重新綁定可以處理此情形。該變量必須是執行緒區域的（或必須使用大的互斥, mutex），因此這個情況不會在執行緒下斷開：動態作用域的實作也可以處理此情形。
在Common Lisp函式庫中有很多標準的特殊變量。例如，所有標準I/O流都儲存在頂層為眾所熟知的特殊變量的綁定中，即*standard-output*。
假設有個foo函數寫入標準輸出：
  (defun foo ()
    (format t "Hello, world"))
要擷取其輸出中的字串，*standard-output*可以被綁定到一個字串流，並調用它：
  (with-output-to-string (*standard-output*)
    (foo))
 -> "Hello, world" ; gathered output returned as a string

區域

Common Lisp支援詞法環境。形式上，詞法環境中的綁定具有詞法作用域，並可能具有不定的範圍或動態的範圍，取決於命名空間的類型。詞法作用域實際上表示可見性被限制在綁定建立的區塊中。參照沒有以文本（即詞法地）嵌入在該區塊中，根本看不到該綁定。
TAGBODY中的標籤會具有詞法作用域。如果(GO X)表達式實際上沒有嵌入到其中，則它會發生錯誤。TAGBODY包含標籤X。但是當TAGBODY執行終了時，標籤的綁定就會消失，因為它們具有動態作用域。如果以調用一個詞法閉包重新進入該代碼區塊，那麼這個閉包的內文無法藉由GO將控制轉移到標籤中：
  (defvar *stashed*) ;; will hold a function

  (tagbody
    (setf *stashed* (lambda () (go some-label)))
    (go end-label) ;; skip the (print "Hello")
   some-label
    (print "Hello")
   end-label)
  -> NIL
執行TAGBODY時，它首先評估以setf形式指向函數的特殊變量*stashed*，然後(go end-label)將控制項轉移到終了標籤，跳過代碼(print "Hello")。由於終了標籤位於TAGBODY的末端，於是終止並返回NIL值。假設現在調用先前指向的函數：
  (funcall *stashed*) ;; Error!
這種狀況是錯誤的。一個實作的錯誤回應該包含錯誤條件訊息，例如「GO: tagbody for tag SOME-LABEL has already been left」。該函數嘗試評估(go some-label)，它是詞法地嵌入到TAGBODY中並解析為標籤。然而TAGBODY被跳過了而沒有執行（其作用域已經結束），故無法再轉移控制。
Lisp中的區域函數綁定具有詞法作用域，預設情況下變量綁定也同樣為詞法作用域。與GO標籤對比，它們的作用域是範圍不定的。當一個詞法的函數或變量綁定時，既然可以對其引用參照，該綁定就會持續存在，即使在建立該綁定的結構已經終止後。參照到詞法變量和函數，在其建立結構終止後，可以藉由詞法的閉包來實現。
Common Lisp對於變量的預設模式是詞法綁定。對於個別符號可用區域聲明，或全局的聲明，來切換成動態作用域。而後者可能隱含地透過如DEFVAR或DEFPARAMETER，這樣的構造使符號成為全局可見的。Common Lisp編程中慣例以開頭和結尾星號*，將特殊變量（即處於動態作用域的）包括起來，這稱為「耳罩慣例」。遵循此慣例的效果，即為特殊變量創建了一個單獨的命名空間，則應該處於詞法作用域的變量不會被意外地特殊化。
幾個原因使得詞法作用域有用。
首先，變量和函數的參照可以被編譯成高效的機器碼，因為執行期環境的結構相對簡單。在許多情況下它可以優化堆疊存儲，因此開啟和關閉的詞法作用域前置開銷最小。即使在必定要產生完整閉包的情況下，存取閉包的環境仍然是有效率的；每個變量通常會轉成一個綁定向量之中的偏移量，因此變量的參照就成為簡單的加載，或是以基底-加-偏移尋址模式表示的存儲指令。
其次詞法作用域（與不定範圍結合）可以創造出詞彙閉包，從而產生了中心以函數作為第一類物件的編程範式，這是函數式編程的根本。
第三，也許最重要的是，即使沒有用到詞法的閉包，詞法作用域的運用，會將程序模組與不需要的交互影響隔離開來。由於可見性受到限制，詞法變量是私有的。如果一個模組A綁定一個詞法變量X，並呼叫另一個模組B，則參照B其中的變量X，不會被意外地解析成在A中綁定的X。B根本無法存取X。對於需使用變量進行有規則的交互作用情況，Common Lisp提供了特殊變量。特殊變量允許一個模組A設置變量X的綁定，使另一模組B能看見並從A調用其中的X。能夠做到這一點是個優勢，能夠防止它發生也是個優勢；因此Common Lisp同時支援詞法和動態作用域兩者。

使用宏定義控制結構的範例

Lisp編程人員能夠利用宏來創造新的語法形式。典型的用途是創建新的控制結構。

此處提供一個until循環結構的宏範例，其語法如下：
(until test form*)
until宏的定義：
(defmacro until (test &body body)
  (let ((start-tag (gensym "START"))
        (end-tag   (gensym "END")))
    `(tagbody ,start-tag
              (when ,test (go ,end-tag))
              (progn ,@body)
              (go ,start-tag)
              ,end-tag)))
tagbody是一個基本的Common Lisp運算子，它提供了命名標籤的能力，並使用go形式跳轉到這些標籤。

反引號`的用途類似單引號'（相當於quote函數，引用形式當成資料而不求值），它還是一個可作代碼模板

的符號，其中需要求值的形式參數以逗號,開頭填入模板；而以,@符號為開頭的形式參數，其中嵌套的內容會

再被拆解評估。tagbody形式測試結束條件。如果條件為真，則跳轉到結束標籤；否則執行主體的代碼，

然後跳轉到起始標記。
上述until宏的使用範例：
(until (= (random 10) 0)
  (write-line "Hello"))
利用macroexpand-1函數可以展開宏的代碼。上例經過展開後的代碼如下所示：
(TAGBODY
 #:START1136
 (WHEN (ZEROP (RANDOM 10))
   (GO #:END1137))
 (PROGN (WRITE-LINE "hello"))
 (GO #:START1136)
 #:END1137)
在宏展開期間，變量test的值為(= (random (10) 0)，變量body的值為((write "Hello"))，是一個列表形式。
符號通常會自動轉成英文大寫。這個TAGBODY擴展中帶有兩個標籤符號，由GENSYM自動產生，並且不會被拘束到任何套件中（為待綁定的暫時自由變量）。兩個go形式會跳轉到這些標籤，因為tagbody是Common Lisp中的基本運算子（並不是宏），因此它沒有其它內容會再展開。展開形式中用到的when宏也會再展開。將一個宏完全展開為源代碼的形式，被稱為代碼走開（code walking）。在已被完全展開的形式中，when宏會被基本運算子if代換：
(TAGBODY
 #:START1136
 (IF (ZEROP (RANDOM 10))
     (PROGN (GO #:END1137))
   NIL)
 (PROGN (WRITE-LINE "hello"))
 (GO #:START1136))
 #:END1137)
源碼中所有包含的宏必須在展開之後，才能正常地評估或編譯。宏可以理解為接受和返回抽象語法樹（Lisp S-表達式）的函數。
這些函數會在求值器或編譯器調用之前，將宏內容轉換為完整的源碼，Common Lisp中所提供的任何運算子都可用於編寫宏。

條件系統

條件系統負責Common Lisp中的異常處理。它提供條件，處理程序和重新啟動。條件是描述異常情況（例如錯誤）的物件。如果一個條件訊號被發出了，Common Lisp系統將搜索此條件類型的處理程序並調用它。處理程序現在可以搜索重新啟動（restart），並使用這些重新啟動之一來自動修復當前的問題，利用條件類型與條件物件的一部份所提供的任何相關資訊等，並調用相對的重新啟動函數。
如果沒有處理程序的代碼，這些重新啟動可以對使用者顯示選項（作為使用者介面的一部分，例如除錯器），讓使用者選擇和調用提供的重新啟動選項。由於條件處理程序在錯誤的上下文中被調用（堆疊仍未清空），在許多情況下對錯誤的完全回復處理是可行的，而不同於其它的異常處理系統可能已經終止了當前的執行程序。除錯器本身也可以使用*debugger-hook*這個動態變量來客製或替換。在unwind-protect中寫明的代碼，譬如作為終結，也會適當地被執行例外。
以下範例（使用 Symbolics Genera）中，使用者從讀取求值列印循環（REPL，即頂層）呼叫一個test函數，嘗試開啟一個檔案，而當此檔案不存在時，Lisp系統則呈現四個重新啟動的選項。使用者選擇了s-B:這個重新啟動選項，並輸入不同的路徑名稱（以lispm-init.lisp取代了lispm-int.lisp）。使用者執行的源碼中並沒有包含任何錯誤處理。整個錯誤處理和重新啟動代碼是由Lisp系統本身所提供，它可以處理和修復錯誤，而不終止使用者執行中的程序碼。
Command: (test ">zippy>lispm-int.lisp")

Error: The file was not found.
       For lispm:>zippy>lispm-int.lisp.newest

LMFS:OPEN-LOCAL-LMFS-1
   Arg 0: #P"lispm:>zippy>lispm-int.lisp.newest"

s-A, <Resume>: Retry OPEN of lispm:>zippy>lispm-int.lisp.newest
s-B:           Retry OPEN using a different pathname
s-C, <Abort>:  Return to Lisp Top Level in a TELNET server
s-D:           Restart process TELNET terminal

-> Retry OPEN using a different pathname
Use what pathname instead [default lispm:>zippy>lispm-int.lisp.newest]:
   lispm:>zippy>lispm-init.lisp.newest

...the program continues

Common Lisp 物件系統(CLOS)

Common Lisp包含了物件導向編程的工具包，Common Lisp物件系統或簡稱為CLOS，它是最強大的物件系統之一。Peter Norvig 解釋了在具備CLOS的動態語言中，如何使用其功能（多重繼承，混合，多方法，元類，方法組合等），以達成設計模式更簡單的實現。曾經有幾個擴展被提出來作為Common Lisp ANSI標準的物件導向編程應用，而最終採用了CLOS作為Common Lisp的標準物件系統。
CLOS是個具有多個分派和多重繼承的動態物件系統，並且與靜態語言（如C++ 或Java）中的OOP設施截然不同。作為動態物件系統，CLOS允許在執行時期對泛型函數和類別進行更改。方法可以添加和刪除，類別可以添加和重新定義，物件可依照類別的變動更新，而物件所屬的類別也可以更改。CLOS已經整合到ANSI Common Lisp中。泛型函數可以像普通函數一樣使用，並且是第一類資料類型。每個CLOS類別都已被整合到Common Lisp類別系統中。
Common Lisp中許多型別都有一個相對應的類別。規範中沒有說明CLOS實作的條件，CLOS進階用法的可能性並不是Common Lisp的ANSI標準，CLOS的用處有更多的潛能。一般Common Lisp實作將CLOS用於路徑名稱、流、輸入/輸出、條件，CLOS本身等等。

編譯器和直譯器

早期Lisp方言的幾個實現提供了直譯器和編譯器，不幸的是兩者之間語義是不同的。這些早期的Lisps在編譯器中實作了詞法作用域，在直譯器中實作了動態作用域。Common Lisp要求直譯器和編譯器兩者皆預設使用詞法作用域。Common Lisp標準描述了直譯器和編譯器的語義。可以使用compile
函數呼叫編譯器，來編譯各個函數，並使用compile-file函數編譯源碼檔案。Common Lisp允許類型別聲明，並提供產生編譯器代碼的選擇。後者有優化參數可選擇0（不重要）和3（最重要）之間的值：會影響到執行速度，空間，安全性，除錯和編譯速度。
還有一個函數用來評估Lisp源碼：eval。eval將源碼視為預先解析的S-表達式，而不像其它語言只當成字串處理。這樣可以用常見的Lisp函數來建構代碼，用來構造列表和符號，然後以eval函數來評估該代碼。幾個Common Lisp實作（如Clozure CL和SBCL）以它們的編譯器來實現eval。這樣子即使用eval函數進行評估時，源碼也是會被編譯。
使用compile-file函數呼叫檔案編譯器，產生的編譯檔稱為fasl（快速加載，fast load）檔案。這些fasl檔案和源碼檔案都能以load功能，加載到運行的Common Lisp系統中。根據實作，檔案編譯器會產生位元組碼（例如Java虛擬機），C語言代碼（然後以C編譯器編譯）或直接使用原生機器碼。
即使源碼已經完全被編譯，Common Lisp實作可以和使用者互動。因此，Common Lisp的互動介面並非類比於直譯腳本的設想。
這個語言區隔了讀取時期、編譯時期、加載時期和執行時期，並讓使用者編程在需求的步驟中，也依照這些區別來執行所需的處理種類。
有些特殊的運算子特別適合互動式開發；譬如，若defvar還沒有任何綁定時，則只對提供給它的變量進行賦值；而defparameter總是會執行賦值。在實時映像中互動地評估，編譯和載入代碼時，這種區別是有用的。還有一些功能也幫助撰寫編譯器和直譯器。符號由第一類物件所組成，可由使用者的代碼直接操縱。progv基本運算子允許以編程方式創造詞法綁定，也可以運用套件。Lisp編譯器本身在運行時可用來編譯檔案或單一函數，這使得Lisp成為其它編程語言的中途編譯器或直譯器變得容易。

生日悖論

以下程序計算一個房間內最小數量的人，其完全獨特生日的概率小於 50％（生日悖論，1 人的概率明顯為 100％，2 為 364/365 等）。答案是 23。
;;  By convention, constants in Common Lisp are enclosed with + characters.(defconstant +year-size+ 365)(defun birthday-paradox (probability number-of-people)
  (let ((new-probability (* (/ (- +year-size+ number-of-people)
                               +year-size+)
                            probability)))
    (if (< new-probability 0.5)
        (1+ number-of-people)
        (birthday-paradox new-probability (1+ number-of-people)))))
使用REPL呼叫函數用例：
CL-USER > (birthday-paradox 1.0 1)
23

排序列表

我們定義一個人員類別和一個顯示姓名和年齡的方法。接下來，我們將一組人定義為人物物件列表。然後我們遍歷排序列表。
(defclass person ()
  ((name :initarg :name :accessor person-name)
   (age  :initarg :age  :accessor person-age))
  (:documentation "The class PERSON with slots NAME and AGE."))(defmethod display ((object person) stream)
  "Displaying a PERSON object to an output stream."
  (with-slots (name age) object
    (format stream "~a (~a)" name age)))(defparameter *group*
  (list (make-instance 'person :name "Bob"   :age 33)
        (make-instance 'person :name "Chris" :age 16)
        (make-instance 'person :name "Ash"   :age 23))
  "A list of PERSON objects.")(dolist (person (sort (copy-list *group*)
                      #'>
                      :key #'person-age))
  (display person *standard-output*)
  (terpri))
它以降序列印三個名字。
Bob (33)
Ash (23)
Chris (16)

平方指數

使用LOOP宏：
(defun power (x n)
  (loop with result = 1
        while (plusp n)
        when (oddp n) do (setf result (* result x))
        do (setf x (* x x)
                 n (truncate n 2))
        finally (return result)))
使用示例：
CL-USER > (power 2 200)
1606938044258990275541962092341162602522202993782792835301376
與內建的求冪函數比較：
CL-USER > (= (expt 2 200) (power 2 200))
T

Common Lisp與Scheme的比較

Common Lisp經常和Scheme互相比較，因為它們是最受歡迎的兩種Lisp方言。Scheme早於CL，不僅來自同一個Lisp傳統，而且來自同一位工程師Guy L. Steele，與Gerald Jay Sussman設計的，Guy L. Steele也擔任過Common Lisp標準委員會的主席。
Common Lisp是一種普遍用途的的編程語言；相反的如Emacs Lisp和AutoLISP這兩種Lisp的變體，則是嵌入特定產品作為擴展用的語言。與許多早期的Lisps不同，Common Lisp（Scheme同樣）對源碼直譯和編譯時，預設為詞法變量作用域。
大部份Lisp系統（如ZetaLisp和Franz Lisp）的設計，促成了Common Lisp在直譯器中使用動態作用域的變量，並在編譯器中使用了詞法作用域的變量。由於ALGOL 68的啟發，Scheme引入了Lisp對詞法作用域變量的單一使用；這被廣泛認同是好主意。CL也支援動態作用域的變量，但必須將其顯式聲明為「特殊」。ANSI CL直譯器和編譯器之間的作用域界定是沒有差別的。
Common Lisp有時被稱為Lisp-2，而Scheme被稱為Lisp-1。它指的是CL對函數和變量使用個別的命名空間（實際上CL有許多命名空間，例如go標籤，block名稱和loop關鍵字）。在涉及多個命名空間的權衡之間，CL與Scheme倡導者之間存在著長期的爭議。在Scheme中（廣義地）必須避免與函數名稱互相衝突的變量名稱；Scheme函數通常擁有名稱為lis，lst或lyst的參數，以免與系統內建的list函數衝突。然而在CL中，在傳遞函數作為參數時一定要顯式地引用函數的名稱空間，這也是一個常見的事件，如前面小節中的排序編程範例。
在處理布爾邏輯值時，CL也與Scheme不同。Scheme使用特殊值#t和#f來表示邏輯真與假值。而CL遵循使用符號T和NIL的傳統Lisp慣例，NIL同時也是空列表。在CL中任何非NIL值被條件處理為真，例如if；而在Scheme當中，所有非#f值被視為真。這些慣例約定允許這兩種語言的一些運算子同時作為謂詞（回應邏輯上的是非問題），並返回一個作用值進行進一步的計算，但在Scheme的布爾表達式中，等同於Common Lisp空列表的NIL值或'()，會被評估為真。
最後，Scheme的標準文件要求尾部呼叫優化，而CL標準沒有。不過大多數CL實作會提供尾部呼叫優化，雖然通常只在程序員使用優化指令時。儘管如此，常見的CL編程風格並不偏好於Scheme中普遍使用的遞歸樣式- 一個Scheme程序員會使用尾部遞歸表達式，CL使用者則通常會用do，dolist，loop等疊代表達式，或使用iterate套件來表達。