Mastering clojure macros 读书笔记

这是花了一周时间的阅读笔记,Mastering clojure macros提到的computation 还是不太理解。


1.1. build a solid foundation

1.1.1. macro is ladder: code becomes data then data become data

1.1.1.1. input args(function) acting on data

1.1.1.2. treat the code of arguments as data, create a new expression by evaluating the code that makes up the body of the macro

1.1.1.3. verb: function, macro ,special form ( define in coljure language ,can’t create a customer’s special form)

1.1.2. expand macro

1.1.2.1. macroexpand

1.1.2.1.1. if we have a macro that expands to another macro call, macoexpand will do that do that second expandsion for us, but macroexpand-1 will not

1.1.2.2. macroexpand-1

1.1.2.3. sometime expand correct is error,tow projects try to correctly everything

1.1.2.3.1. https://github.com/clojure/tools.macro

1.1.2.3.2. https://github.com/ztellman/riddley

1.1.3. Subtopic


1.2. Advance your macro techiques

1.2.1. Syntax(·) and unquoting(~)

1.2.1.1. 使用list ~ ,可能由于redefine 函数导致macro在不同namespace 执行不同,而~(syntax quote)可以避免类似问题

1.2.2. GenSym(generate symbol)

1.2.2.1. 在变量后面带"#'号

1.2.2.2. 主要用于macro(匿名函数)内定义参数,避免参数与外部def/let 对象产生歧义和冲突

1.2.3. macro special form

1.2.3.1. &Form

1.2.3.1.1. expression that was used to call the macro (调用macro的语句,包括参数)

1.2.3.2. &Env

1.2.3.2.1. a map of local variables

1.2.4. '~k 等同(quote k) and (list `quote k)


1.3. use your powers wisely

1.3.1. macros aren’t values

1.3.1.1. 不能把macro当做值,macro返回是待执行(函数)

1.3.2. macros can be contagious(传染)

1.3.2.1. macros aren’t values,调用有问题可能需要新定义一个macro

1.3.2.2. example 使用apply,去掉其实就可以调用,无需写macro


1.4. macros can be tricky to get right

1.4.1. 小心测试macro,避免argument重复执行

1.4.2. 使用内置let+gensym 避免arg被多次重复执行


1.5. extensible data notation (edn)


1.5.1. Clojure’s reader supports a superset of extensible data notation (edn).


1.6. evaluate code in context

1.6.1. dynamic bindings

1.6.1.1. (declare ^:dynamic radius)

1.6.1.2. (binding [radius 10.0]

1.6.2. a non-macro approach

1.6.2.1. wrapping a macro as a thin wrapper around a function

1.6.3. evaluating (or not) in time and place

1.6.3.1. ^:once 代表decorated var 只能被使用(执行)一次

1.6.4. rescuing error

1.6.4.1. 使用内部tray-catch 避免错误不断传递

1.6.5. cleaning up resource

1.6.5.1. 使用try finally关闭resource


1.7. speed up your systems

1.7.1. 使用criterium 进行bench (速度)测试

1.7.2. 使用set! warn-on-reflection 关注clojure常见性能问题-reflection

1.7.3. 加速方法

1.7.3.1. 使用^String 等降低arguments的reflection代价

1.7.3.2. 使用clojure原生及优秀类库替代自行开发

1.7.4. :jvm-opts ^:replace []


1.8. bend control flow to your will

1.8.1. Turning expression inside out with threading macros

1.8.1.1. -> thread first

1.8.1.2. ->> thread last

1.8.2. delimtied( 界定) continuations

1.8.2.1. 使用continuations,pause that execution of your code ,captuure is environment and save a reference to the that environment to use later

1.8.2.2. 使用delimc的reset 和shift 实现continuations,加速执行效率

1.8.2.2.1. 循环(递归)调用

1.8.2.3. shift expresstion is able to decide whether or not to continue executing the body of rest

1.8.2.4. k# 是shift 里面的continuations,默认绑定好的

1.8.2.5. Continuation则是另一种函数调用方式。它不采用堆栈来保存上下文,而是把这些信息保存在continuation record中。这些
continuation record和堆栈的activation record的区别在于,它不采用后入先出的线性方式,所有record被组成一棵树(或者图
),从一个函数调用另一个函数就等于给当前节点生成一个子节点,然后把系统寄存器移动到这个子节点。一个函数的退
出等于从当前节点退回到父节点。  
  这些节点的删除是由garbage collection来管理。如果没有引用这个record,则它就是可以被删除的。

1.8.2.6. CPS: contiuation passing style


1.9. implement new language features

1.9.1. implementing pattern matching

1.9.2. error handling in macros

1.9.3. code-walking (代码走查) macros

1.9.3.1. clojure.walk

1.9.3.2. riddley.walk

猜你喜欢

转载自blog.csdn.net/weixin_40455124/article/details/114711463