lisp宏和c 宏有什么区别?
代码即数据是什么意思?这里指的数据是什么,指类似xml的文件数据,还是字符串数据?
s表达式和lisp宏有什么关系,说是让lisp宏更强大,但我一直无法明白。百度了很多次没有找到易懂的回答,希望有个简小的例子说明一下。
lisp宏和c 宏有什么区别?
代码即数据是什么意思?这里指的数据是什么,指类似xml的文件数据,还是字符串数据?
s表达式和lisp宏有什么关系,说是让lisp宏更强大,但我一直无法明白。百度了很多次没有找到易懂的回答,希望有个简小的例子说明一下。
lisp宏就是用代码写代码,c宏相当于字符串替换类似makefile里的变量,代码即数据,这里的数据表示lisp代码本身,和第一条一个意思,宏和程序的起点一样过程一样但是目的不一样,程序是给计算机的,宏是准备给计算机的。这东西还是得学,要不还是不懂
相当于带if while的c宏,有点像cpp的模板元编程吗,还是相当于写编译器的感觉?
比如说我们对一个表达式(conj [1 2] 3)
不急于求值,而是引用,有 (def expr '(conj [1 2] 3))
这个时候我们可以对这个表达式进行操作。
用一个unless的例子(Clojure)
(defmacro unless [test & then]
`(if (not ~test)
(do
~@then)))
(unless false
(println "hello world"))
在宏中,传入的表达式先会被转为抽象语法树再操作,而不是像函数那样传入nil到unless
什么意思???
写错了,该了一下
这里用的是Clojure
如果这个unless是一个函数,调用(unless false (println "hello world"))
会把(prinltn “hello world”)的返回值nil传入unless
宏就是把
这个传进去,不求值,直接传是吗,我懂了什么是代码即是数据了,代码和int,float,double,function之类的数据都是可以直接传进去,只不过通过宏吧。
如果你知道了C的宏了的话,Lisp的宏目的上和C的宏是一样的,都是用一个东西代替一段代码。 但是Lisp的代码本身也是Lisp数据结构的字面量,比如说
(+ 1 2 3)
这是一个表达式,执行的话求值得6,如果不求值的话就是一个List有四个元素:+
, 1
, 2
, 3
. 这个就是代码即数据。
好处就是:因为宏是用来生成代码的,所以宏里面的逻辑实际上是在拼代码,比如说你有一个+
(一个符号)和一个(1 2 3)
一个list, (cons '+ '(1 2 3))
就得到了(+ 1 2 3)
,像这样操作数据结构会比操作字符串要容易的多。所以Lisp的宏会比较好写。
我看子龙山人在 21 天里举的宏的例子 Master Emacs in 21 Days
(defun prelude-search (query-url prompt)
"Open the search url constructed with the QUERY-URL.
PROMPT sets the `read-string prompt."
(browse-url
(concat query-url
(url-hexify-string
(if mark-active
(buffer-substring (region-beginning) (region-end))
(read-string prompt))))))
(defmacro prelude-install-search-engine (search-engine-name search-engine-url search-engine-prompt) ; #1
"Given some information regarding a search engine, install the interactive command to search through them"
`(defun ,(intern (format "prelude-%s" search-engine-name)) () ; #2
,(format "Search %s with a query or region if any." search-engine-name) ; #3
(interactive)
(prelude-search ,search-engine-url ,search-engine-prompt))) ; #4
(prelude-install-search-engine "google" "http://www.google.com/search?q=" "Google: ") ; #5
(prelude-install-search-engine "youtube" "http://www.youtube.com/results?search_query=" "Search YouTube: ")
(prelude-install-search-engine "github" "https://github.com/search?q=" "Search GitHub: ")
(prelude-install-search-engine "duckduckgo" "https://duckduckgo.com/?t=lm&q=" "Search DuckDuckGo: ")
这个例子我是看明白了,可是对于这么写的目的没太想明白,为什么不直接写一个传入 search-engine-name search-engine-url search-engine-prompt 这三个参数的 prelude-search
函数,反而要用宏来生成了4个名称不同的函数呢?生成4个名称不同的函数有什么好处么?
这四个函数是interactive的,搜索的时候可以直接用对应搜索引擎,不需要再输入引擎的参数,当然你可以写成一个函数,调用的时候多一个引擎的参数输入,完全没问题,就是麻烦点
简书上有篇宏的解释和举例:
谢谢,这么一看用宏来生成函数的确是方便不少。