前一篇《 第一聲問候》講述瞭如何用 Emacs Lisp 寫一個能夠在 Emacs 計算機裏運行的 hello world 程序。
咱們已經經過一個極爲簡單的 hello-world
函數,向 Emacs 計算機發出了第一聲問候。編程
這個 hello-world
函數的定義很是簡單:segmentfault
(defun hello-world () (interactive) (insert "hello, world"))
可是一旦弄懂了如何使用 Emacs Lisp 語言定義一個函數,以及 interactive
與 insert
的用法,咱們就能夠在不少時候從一個勤勞的人蛻變爲一個懶惰的人。函數
此前,有一段時間,我常常用 POV-Ray [1] 渲染一些很簡單的三維場景:我向 POV-Ray 提供場景文件,由 POV-Ray 使用光線追蹤技術基於場景文件中的描述完成三維渲染。每份 POV-Ray 場景描述文件每每是如下面內容做爲開始:code
#version 3.7; #include "colors.inc" global_settings { assumed_gamma 1.0 }
一開始我比較勤勞,會在每份場景文件中很認真地手動輸入上述內容。如今就能夠沒必要如此,在 init.el 中像下面這樣定義一個函數:orm
(defun povray-head () (interactive) (insert "#version 3.7\n" "#include \"colors.inc\"\n\n" "global_settings {\n" " assumed_gamma 1.0\n" "}\n"))
這樣,每次當我新建了一份 POV-Ray 場景文件以後,只須要向 Emacs 發送 M-x povray-head <RET>
指令,場景文件中就會自動出現上述內容。get
看,並不須要多麼高超的編程技術,只是將 hello-world
函數略微改動一下,就節省了許多重複性的勞動。從物理學的角度來看,在我編寫許多 POV-Ray 場景描述文件時,這個 povray-head
函數可讓我更省力。數學
因此,在我看來一個程序首先應該是一種有用的機械,它與槓桿、滑輪、斜面這些基本的省力裝置不該該存在本質上的區別。所以,在寫一個程序以前,須要明確,這個程序是否可讓你或讓其餘使用這個程序的人更省力。不省力的程序,是不必去寫的。string
最近爲了寫幾篇 Emacs Lisp 編程方面的文章,我不得不在 Emacs 裏編程。實際上我也常常須要使用 C 語言在 Emacs 的宿主系統中編程。我常常須要寫一些像下面這樣的代碼:it
double *foo = malloc(n * sizeof(double));
若沒學過 C 語言,就沒必要在乎這行代碼的含義,將它視爲普通的文本便可。假若手寫這行代碼,我必須寫兩次 double
。如今,我能夠再在 init.el 中定義一個 c-malloc
函數,讓我在寫此類代碼時可以省點力。io
如下是 c-malloc
的定義:
(defun c-malloc (name type n) (interactive (list (read-string "變量名稱?") (read-string "類型?") (read-string "數量?"))) (insert (format "%s *%s = malloc(%s * sizeof(%s));" type name n type)))
這個函數的定義,與 hello-world
以及 povray-head
不同,它是帶有參數的函數。與後二者相比,它更符合咱們在數學中對函數創建的通常性認識,即 w = f(x, y, z) 或 f: (x, y, z) -> w。
暫時不考慮 c-malloc
的細節,先看它是如何工做的。
如今,假若 Emacs 從新加載了 init.el 文件,那麼使用 M-x c-malloc <RET>
指令即可讓 Emacs Lisp 解釋器對 c-malloc
進行求值,可是 Emacs 在執行上述指令後,會在微緩衝區裏問我三個問題。
第一個問題是:
變量名稱?
我(在微緩衝區裏)輸入指令 foo <RET>
,就回答了這個問題。緊接着,Emacs 會再問:
類型?
我輸入指令 double <RET>
,就回答了這個問題。最後,Emacs 會問:
數量?
我回答 n <RET>
。
注:<RET>
表示單擊回車鍵。例如n <RET>
,表示輸入n
以後,單擊回車鍵。
回答了這三個問題以後,Emacs 就會在緩衝區裏顯現:
double *foo = malloc(n * sizeof(double));
實際上,Emacs 接受個人答案以後,會將它們依序分別綁定到 c-malloc
的三個參數 name
、type
、n
上,這就至關於造成了下面的表達式:
(c-malloc "foo" "double" "n")
接下來,Emacs Lisp 解釋器對這個表達式進行求值,結果就是在緩衝區裏插入
double *foo = malloc(n * sizeof(double));
像這些瑣碎可是出現頻率比較高的代碼片斷,花一點時間,用編程的方式來生成它們,不只省力,並且也避免了手工輸入的錯誤。一個勤勞的人,應該用編程的方式讓本身變懶,而不是讓本身活成一段程序。
上文中出現的 Emacs Lisp 代碼,看不懂沒有關係,由於在下一篇就開始講述 Emacs Lisp 的文本處理方面的編程知識。
下一篇: 原子與虛空