Clojure 学习入门(11)- 宏 macro
- 能写成函数就不要用宏(因为写宏没有写函数简单直观,容易写错,需要先在 REPL 中测试一番)
- 只有不得不用时才用宏(性能要求高时比函数调用快,或者需要“代码<->数据”相互转换)
- 精心设计的宏调用比函数调用更 DSL(如实现控制结构、传递 Java方法)
宏与函数
- ;; 宏正确写法
- (defmacro op [x f1 y f2 z]
- (list f2 z (list f1 x y)))
- (println (op 5 + 2 * 10)) ;; 70
- (println (macroexpand '(op 5 + 2 * 10))) ;; (* 10 (+ 5 2))
- (println (macroexpand-1 '(op 5 + 2 * 10))) ;; (* 10 (+ 5 2))
- (println (clojure.walk/macroexpand-all '(op 5 + 2 * 10))) ;; (* 10 (+ 5 2))
- ;; 宏错误写法
- (defmacro op2 [x f1 y f2 z]
- ( f2 z (f1 x y)))
- (println (op2 5 + 2 * 10)) ;; 2
- (println (macroexpand '(op2 5 + 2 * 10))) ;; 2
- (println (macroexpand-1 '(op2 5 + 2 * 10))) ;; 2
- (println (clojure.walk/macroexpand-all '(op2 5 + 2 * 10))) ;; 2
- ;; 不使用宏
- (defn op3 [x f1 y f2 z]
- ( f2 z (f1 x y)))
- (println (op3 5 + 2 * 10)) ;; 70
- (println (macroexpand '(op3 5 + 2 * 10))) ;; (op3 5 + 2 * 10)
- (println (macroexpand-1 '(op3 5 + 2 * 10))) ;; (op3 5 + 2 * 10)
- (println (clojure.walk/macroexpand-all '(op3 5 + 2 * 10))) ;; (op3 5 + 2 * 10)
说明:
正确的宏写法,需要添加 list,宏用defmacro定义,不用宏写法的函数用defn定义
调试宏,用macroexpand展开
宏符号
` |
原原本本地直译过去,不用`,let语句不被翻译,例如: (let [datastr '{:a 1 :b 2}]) |
~' |
后面的变量被直接翻译过去,例如:(let [~'conn "meta"] (with-mongo ~'conn)) |
'~ |
变量名本身而非值,例如:(defn f1 [x] (println '~x ":" ~x)) (let [a 10] (f1 a)) ;; a:10 |
~@ |
表示多条语句 |
示例1:
- (defmacro debug [x] `(println "---" '~x ":" ~x))
- (let [a 10] (debug a)) ;; --- a : 10
说明:
'~x 显示变量名,即a
~x 解析为变量值,即a的值 10
示例2:
- (defn make-connection [x] (println "in make-connection = " x) x) ;; meta
- (defn with-mongo [x] (println "in with-mongo = " x)) ;; meta
- (defmacro with-dict
- "连接到 meta库的 dict表进行操作"
- [& body]
- `(let [~'dbname "meta"
- ~'tbname :dict
- ~'conn (make-connection ~'dbname)
- ]
- (with-mongo ~'conn)
- (println "~'conn = " ~'conn) ;; meta
- (println "~'tbname = " ~'tbname) ;; :dict
- (println "~@body = " ~@body) ;; meta :dict db-test2' tbl-test2'
- ~@body))
- (let [dbname 'db-test'
- tbname 'tbl-test'
- dbname2 'db-test2'
- tbname2 'tbl-test2'
- conn 'conn-sql'
- make-connection 'make-conn'
- body 'body1']
- (with-dict dbname tbname dbname2 tbname2))
运行结果:
in make-connection = meta
in with-mongo = meta
~'conn = meta
~'tbname = :dict
~@body = meta :dict db-test2' tbl-test2'
说明:
make-connection 和 with-mongo 是定义的函数,后面传递的是参数,使用 ~' 修饰直接翻译过去,即字符串传字符串,:dict 键值也传键值
with-dict 传递多个参数给body,其中 dbname tbname 在 with-dict 中被重新赋值,因此打印出的结果也为赋值后的最新结果
Clojure 学习入门(11)- 宏 macro相关推荐
- Clojure 学习入门(6)- 函数定义
一.创建函数: fn: fn是一个宏,用于定义一个简单的函数,如下: [python] view plaincopy print? user=> (fn [] "hello&quo ...
- Clojure 学习入门(6)—— 函数定义
一.创建函数: fn: fn是一个宏,用于定义一个简单的函数,如下: user=> (fn [] "hello") #<user$eval375$fn__376 us ...
- Clojure 学习入门(16)- 正则表达式
一.创建正则表达式 re-pattern函数: 函数 (re-pattern) 接受一个字符串参数,返回一个正则表达式样式(java.util.regex.Pattern类的实例).这个样式能用于 ...
- Clojure 学习入门(13)- binding
Clojure里面是不支持变量的.Binding跟变量有点像,但是在被赋值之前是不允许改的,包括:全局binding, 线程本地(thread local)binding, 以及函数内的本地bindi ...
- Clojure 学习入门(1) - 学习资料
转自:http://blog.csdn.net/ithomer/article/details/17225813 Clojure(发音类似"closure",['kləʊʒə(r) ...
- Clojure 学习入门(15)- 条件判断
一.标准的流程控制 if: 将一个判断表达式作为它的第一个参数进行求值.如果求值为true,那么就返回它的第二个参数(相当于"then"子句)的求值结果.如果结果为false( ...
- Clojure 学习入门(14)- 循环控制
Clojure 基于函数的流程控制 repeatedly 字面意思为重复函数.一般的用法如下: user=> (repeatedly 5 #(rand-int 11)) (6 8 2 6 6) ...
- Clojure 学习入门(7)- 连接mysql
Clojure的contrib包中实现了对现有JDBC的封装,在wiki上有连接,该页面上包含了对不同的数据库的连接方法和基本的操作,但是这个页面上没有提供足够的信息,足够一个初学者能够使用Cloju ...
- Clojure 学习入门(3)- 数字类型
一.算术运算 加法+:加法函数(+)接受任意数值类型的参数,返回它们的和:没有参数时返回0. [python] view plaincopy print? $clojure Clojure 1.2 ...
最新文章
- 【Kotlin】Kotlin 语言集合中的高阶函数详解 ( 数据类 data class | maxBy | minBy | filter | map | any | count | find )
- STM32F103 CAN中断发送功能的再次讨论
- opython3l_Python从小白到攻城狮(3)——列表和元组,到底用哪个?
- C语言gauss elimination高斯消元法算法(附完整源码)
- linux锐捷认证成功无法上网,win7系统锐捷认证成功但是却无法上网的解决方法
- oracle恢复drop建的表首次,案例:Oracle dul数据挖掘 没有备份情况下非常规恢复drop删除的数据表...
- D-query SPOJ - DQUERY (主席树)
- 阿里云ECI如何6秒扩容3000容器实例?
- spring中配置quartz定时器
- asp.net mvc 中直接访问静态页面
- ibatis学习四---执行流程浅析
- 阿里 Maven仓库
- 樊登读书会终身成长读后感_樊登读书会创始人演讲《知识爆炸时代如何终身成长》...
- 英特尔核心显卡控制面板设置自定义分辨率
- Paper intensive reading (二十五):Fecal Viral ...Virion-Enriched Metagenomics and Metatranscriptomics
- 打字母案例完整版(C#)
- Navicat Premium 12.0.22安装与激活
- Atcoder abc A~E
- 苹果手机有便签吗?苹果手机便签下载
- 格创东智亮相高端制造业CIO上海论坛,助推制造业智慧建设
热门文章
- Quartus II调用modelsim ALTEA 的软件使用及问题
- [图解]管理九段的新排列
- SSAS : 如何编写自定义挖掘算法
- 服务器中文档存储在哪,云服务器存储在哪
- python科研计价_科研速递 | 花费15年众望所归!NumPy论文终登上Nature!
- vscode插件之Vetur
- html引入html include_PostgreSQL引入插件EXTENSION的常用方法
- 清华同方计算机教程,清华同方电脑u盘重装系统win10教程
- mongodb 良贴
- 纯CSS3渐变色板配色代码