为什么使用宏
1: (defun prelude-search (query-url prompt) 2: "Open the search url constructed with the QUERY-URL. 3: PROMPT sets the `read-string prompt." 4: (browse-url 5: (concat query-url 6: (url-hexify-string 7: (if mark-active 8: (buffer-substring (region-beginning) (region-end)) 9: (read-string prompt)))))) 10: 11: (defmacro prelude-install-search-engine (search-engine-name search-engine-url search-engine-prompt);; #1 12: "Given some information regarding a search engine, install the interactive command to search through them" 13: `(defun ,(intern (format "prelude-%s" search-engine-name)) ();;#2 14: ,(format "Search %s with a query or region if any." search-engine-name);;#3 15: (interactive) 16: (prelude-search ,search-engine-url ,search-engine-prompt))) ;;#4 17: 18: (prelude-install-search-engine "google" "http://www.google.com/search?q=" "Google: ");;#5 19: (prelude-install-search-engine "youtube" "http://www.youtube.com/results?search_query=" "Search YouTube: ") 20: (prelude-install-search-engine "github" "https://github.com/search?q=" "Search GitHub: ") 21: (prelude-install-search-engine "duckduckgo" "https://duckduckgo.com/?t=lm&q=" "Search DuckDuckGo: ") 22:
下面对以上代码进行讲解:
- 第#1 行, 通过
prelude-install-search-engine
定义了一个需要 3 个参数的宏, 这个 宏的作用是生成一个函数. - 第#2 行, 通过
intern
生成一个符号作为函数名, 名称为prelude-xxx
, 其中 xxx 为第一个参数的值. - 第#3 行, 生成了这个函数的描述.
- 第#4 行, 调用
prelude-search
函数进行搜索处理. - 第#5 行, 调用这个宏定义了一个名为
prelude-google
的函数.
从以上代码可以知道, 我们利用宏生成了4个名称不同的函数, 避免了手动编写函数的问题 (因为这4个函数的代码非常相似, 根据 DRY 原则应该尽量避免做这种重复工作).
关于宏的更多内容, 可以阅读 Paul Graham
的著作 [《On Lisp》](http://www.paulgraham.com/onlisp.html)