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

1 个赞

什么意思???

写错了,该了一下
这里用的是Clojure

如果这个unless是一个函数,调用(unless false (println "hello world")) 会把(prinltn “hello world”)的返回值nil传入unless

1 个赞

宏就是把

这个传进去,不求值,直接传是吗,我懂了什么是代码即是数据了,代码和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的宏会比较好写。

7 个赞

我看子龙山人在 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的,搜索的时候可以直接用对应搜索引擎,不需要再输入引擎的参数,当然你可以写成一个函数,调用的时候多一个引擎的参数输入,完全没问题,就是麻烦点

简书上有篇宏的解释和举例:

谢谢,这么一看用宏来生成函数的确是方便不少。