代码拉取完成,页面将自动刷新
##一次宏体验 ###;必要的引入,可以忽略它们的含义。
(ql:quickload '("restas" "sexml"))
(sexml:with-compiletime-active-layers
(sexml:standard-sexml sexml:xml-doctype)
(sexml:support-dtd
(merge-pathnames "html5.dtd" (asdf:system-source-directory "sexml"))
:<))
###;这是我要实现的效果代码
; (<:ul :class "nav"
; (<:li (<:a :href "#" "首页"))
; (<:li (<:a :href "#" "互动"))
; (<:li (<:a :href "#" "分享"))
; (<:li (<:a :href "#" "动态"))
; (<:li :class "divider-vertical")
; (<:li (<:a :href "#" "会议"))
; (<:li (<:a :href "#" "讨论"))
; (<:li :class "divider-vertical")
; (<:li (<:a :href "#" "关于")))
###;这是生成效果的macro
(defmacro ge-ul(cls &rest lis)
`(let ((j 0) (a1 nil) (k 0) (r nil) (z ,cls))
;(print lis)
(loop for i in (list ,@lis) do
(incf j)
;(print j)
(if (equalp "dv" i)
(progn
;(push "(<:li :class \"divider-vertical\")" r)
(push `(<:li :class "divider-vertical") r)
(setq k (mod j 2)))
(if (= (mod j 2) k)
;(push (concatenate 'string "(<:li (<:a :href \"" a1 "\" \"" i "\"))") r)
(push `(<:li (<:a :href ,a1 ,i )) r)
(setq a1 i)
)))
(reverse r)
`(<:ul :class ,z ,@r)))
###;; 因为使用了sbcl,所以下列纯属为了方便复制粘贴
;; (load "kkk")
;; (ge-ul "nav" "#" "首页" "dv" "#" "产品介绍")
;; (macroexpand-1 '(ge-ul "nav" "#" "首页" "dv" "#" "产品介绍"))
###;;;;宏体验心得:
;;;; 1>逗号(comma)取值需要放到反引号(backquote)中。对于取消求值操作,单引号和
;;;; 反引号的作用是一样的,但是如果要使用comma求值即改变quote的求值方式那么
;;;; 必须是backquote和comma配合使用。
;;;; (comma must be inside a backquote.)
;;;; 2>如果用到内部定义的变量,在使用的时候必须是反引号和逗号连用。否则在不用嵌套
;;;; 反引号时系统提示变量未定义,当你试图使用单引号(quote)时,系统会提示
;;;; comma not inside a backquote。
;;;; 3>一定要勤用macroexpand-1来查看宏展开形式。
;;;; 4>宏应用的核心就是——实参和自定义变量的参悟。
;;;; 5>实参是宏内第一层变量,所以在第一层backquote中如果要求值必须使用comma,而
;;;; 内部定义的变量是第二层变量,它生活在第二层backquote中,所以要使用它必须
;;;; 引入第二层backquote,然后再进行求值comma。这就是上述总结的一起使用的原因。
;;;; 如果一个表达式中要对第一层和第二层变量分别求值,那么最好的办法是以最深层的
;;;; 变量为基准,嵌入backquote,而外层变量通过let绑定到和深层变量相同的生命
;;;; 周期内,然后再求值即可。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。