前一篇《 第一声问候》讲述了如何用 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 的文本处理方面的编程知识。
下一篇: 原子与虚空