勤勞,仍是懶惰?

前一篇《 第一聲問候》講述瞭如何用 Emacs Lisp 寫一個能夠在 Emacs 計算機裏運行的 hello world 程序。

咱們已經經過一個極爲簡單的 hello-world 函數,向 Emacs 計算機發出了第一聲問候。編程

這個 hello-world 函數的定義很是簡單:segmentfault

(defun hello-world ()
  (interactive)
  (insert "hello, world"))

可是一旦弄懂了如何使用 Emacs Lisp 語言定義一個函數,以及 interactiveinsert 的用法,咱們就能夠在不少時候從一個勤勞的人蛻變爲一個懶惰的人。函數

此前,有一段時間,我常常用 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 的三個參數 nametypen 上,這就至關於造成了下面的表達式:

(c-malloc "foo" "double" "n")

接下來,Emacs Lisp 解釋器對這個表達式進行求值,結果就是在緩衝區裏插入

double *foo = malloc(n * sizeof(double));

像這些瑣碎可是出現頻率比較高的代碼片斷,花一點時間,用編程的方式來生成它們,不只省力,並且也避免了手工輸入的錯誤。一個勤勞的人,應該用編程的方式讓本身變懶,而不是讓本身活成一段程序。

上文中出現的 Emacs Lisp 代碼,看不懂沒有關係,由於在下一篇就開始講述 Emacs Lisp 的文本處理方面的編程知識。

下一篇原子與虛空

[1] http://povray.org/

相關文章
相關標籤/搜索