位元詩人 [程式設計] 入門教學 (使用 Lisp):基本概念

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

本文以 Common Lisp 為例,說明剛學程式設計時會碰到的一些基本概念。

檔案名稱 (File Name) 和副檔名 (File Extension)

程式碼本身是文字檔案 (text file)。本節說明和檔案相關的問題。

檔案名稱

大部分程式語言不會限制檔案的名稱,包括 Common Lisp。一般來說,檔案名稱只要簡明、清楚即可。像是 helloworld.lisp 就是用來寫 Hello World 程式的 Lisp 命令稿。

若要用複合字來命名檔案,建議使用 kebab-case (烤肉串命名法)。像是 number-guessing.lisp 是一個猜數字小遊戲。不要在檔名中使用空白 (space),這是自找麻煩的舉動。

Java 是少數會限制檔案名稱的程式語言。像是 MainProgram.java 的內容如下:

public class MainProgram
{
    public static void main (String[] args)
    {
        /* Implement your code here. */
    }
}

在此處,類別名稱 MainProgram 和檔案名稱 MainProgram 必須一致,否則會無法編譯。

副檔名

Unix 的可執行命令稿不需要副檔名。但 Windows 的命令稿仍然要用副檔名來區分檔案格式。故仍建議在程式碼加上副檔名。Common Lisp 程式碼的副檔名是 .lisp

Unix 的可執行檔同樣不需要副檔名。Windows 可執行檔的副檔名是 .exe 。根據編譯 Common Lisp 程式碼時,所在的宿主系統 (host system) 來決定執行檔的副檔名。

編譯 (Compilation) 和直譯 (Interpretation)

執行編譯語言的程式碼,要先將程式碼轉成相對應的執行檔後執行該程式。由於程式碼已經轉換成相對應的機械碼了,不需要每次都從頭轉換,所以執行起來會比較快。

執行直譯語言的程式碼,不需要先編譯,而是即時將命令稿轉為相對應的程式。雖然省下編譯的動作,但每次都要從頭解析程式碼、經轉換後才執行程式,所以執行起來比較慢。

大部分的程式語言只有編譯或直譯其中一種模式。C、C++、Pascal 是編譯語言 (compiled language),Python、Ruby、JavaScript 則是直譯語言 (interpreted language)。至於 Common Lisp 比較特別,有許多實作品兼具編譯和直譯兩種模式。

直譯模式

建立 Common Lisp 命令稿 hello.lisp ,填入以下內容:

(write-line "Hello World")

執行該命令稿:

$ sbcl --script hello.lisp
Hello World

執行該命令稿時不會產生執行檔,所以是直譯模式。

編譯模式

Common Lisp 的編譯模式相對不易使用,需要額外寫指令。本小節展示這個過程。

主程式 main.lisp 的內容如下:

;; The main function.
(defun main ()
   (write-line "Hello World")
   (quit))

這裡的函式 main 是必須的,因為編譯的指令會用到。至於函式名稱 main 只是約定俗成,實際上可以取別的名字。

工具命令稿 make.lisp 的內容如下:

;; Load the main program.
(load "main.lisp")

;; Compile the main program.
(let ((program "program"))
      (when (equal (software-type) "Win32")
        (setq program "program.exe"))
      (sb-ext:save-lisp-and-die program
                                :toplevel #'main
                                :executable t))

;; Quit the utility script.
(quit)

這裡不逐行講解。簡單地說,載入 main 函式後,將該函式當成頂層函式來編譯程式碼。最後離開此命令稿。

編譯後執行主程式:

$ sbcl --script make.lisp
$ ./program
Hello World

由於編譯模式對理解程式設計的概念沒啥幫助,本系列文章日後不會使用此模式。此處僅是展示編譯 Common Lisp 程式碼的過程。

交互性程式設計 (Interactive Programming)

許多程式語言都有交互式環境。這種環境又稱為 REPL (註) 環境。一般來說,交互式環境是用來測試簡短的程式碼,以學習程式設計的概念。但 Lisp 的交互式環境不僅於此,可用來邊撰寫邊執行程式碼,比大部分的程式語言有更快的迭代。

(註) REPL 為 Read-Eval-Print-Loop 的縮寫。

使用先前提到的 SLIMEAlive 等編輯器外掛,就可以用 REPL 模式來撰寫 Lisp 程式碼。

執行 SBCL 的主程式,但不加參數,就會進入 Common Lisp 的交互模式:

$ sbcl
This is SBCL 2.3.2, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* 

輸入 Lisp 指令後,會立即執行及回饋結果給使用者,然後返回提示符:

* (+ 1 2 3 4 5)
15
* 

最後要離開此交互式環境了,就輸入 (quit) 指令:

* (quit)

大小寫敏感性 (Case Sensitivity)

很多程式語言的程式碼將英文大小寫視為相異指令,這種程式語言具有大小寫敏感性。

Common Lisp 程式碼則不具大小寫敏感性。按照社群慣例,會以英文小寫字母來寫程式碼。

空白 (Space)、縮進 (Indentation)、換行 (End of Line)

大部分程式語言不會限制空白、縮進、換行等排版元素。只要程式碼看起來整齊美觀即可。Common Lisp 對這些排版元素也是採取相對寬鬆的態度。

Python 的縮進是有意義的,同一層的程式碼要使用相同深度的縮進。像是以下簡短範例:

def power(base, exp):
    if 0 == exp:
        return 1.0
    elif 0 < exp:
        return power(base, exp - 1) * base
    else:
        return power(base, exp + 1) / base

assert 1 == power(3, 0)
assert 81 == power(3, 4)
assert (1.0/81) == power(3, -4)

在這個例子中,函式使用一層縮進,if 敘述再加上一層縮進。

註解 (Comment)

程式碼是帶有特定語法的文字檔案,在程式碼中加入不符合語法的文字會導致編譯錯誤。

註解的目的是為了在程式碼中加入自由文字 (free text)。加在註解的文字是給程式設計者閱讀的,編譯器或直譯器會忽略註解的內容。

在 Common Lisp 中,位於 ; 後同一行的文字視為註解。但 ; 相對不易閱讀。按照社群慣例,;;;; 用於整份檔案開頭的註解,;; 用於一段程式碼區塊前,; 僅用於程式碼後,簡短的註解。

主函式 (Main Function)

主函式是程式的進入點、起始點。編譯語言通常有主函式,而直譯語言則無。

Common Lisp 在直譯模式時不需要主函式,直接將指令寫在命令稿頂層即可。在編譯模式時,則需要指定一個任意名稱的頂層函式權充該程式的主函式。

離開狀態 (Exit Status)

程式執行完畢時,會回傳一個 0 至 255 間的整數,用來代表程式的狀態。一般來說,0 代表程式執行成功,1 或其他非零的數字則代表執行失敗。

程式設計者可自行設計每個回傳值的意義,但不應偏離社群慣例。最常用的離開狀態是 0 和 1,其他相對少見回傳值則應載明在程式的說明手冊中。

以下 Common Lisp 範例程式回傳執行成功的狀態:

(write-line "Hello World")

;; Quit with status code.
(sb-ext::quit :unix-status 0)
關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。