美文网首页
clojure macro 宏的一点浅见

clojure macro 宏的一点浅见

作者: onedam | 来源:发表于2022-11-18 13:40 被阅读0次
423c5949c3fb887f00cb38156903c94.jpg

工作之余 站在半山腰 清风吹来, 大西北干燥的凛冽,似乎要吹进骨子里,心中升起一种印在灵魂深处的无法言说的亲切感.

从2012年到现在, clojure 在我生命中已经陪伴了快10年了. <黑客和画家> 一书让很多人对 lisp 神向往之 . 在王垠大神的推荐下,浅尝辄止了下chez scheme,但现实中云浩的主要产品全部基于j2ee架构. 直到遇到clojure . 一颗长在java大树上的明珠 (诚然一部分同仁会对这个说法持保守意见,因为java和clojure在思想上差距巨大 一个是面向对象+设计模式, 一个是函数式编程+面向数据) , 但要掌握clojure ,你必须要经过java,要成为一个clojure执业程序员,首先必须要是一个职业java程序员 (爱好者除外)
clojure 学习曲线并不陡峭,一些身边朋友 同事,在遇到宏的时候都感觉有点吃力,值此疫情在老家静居思过. 一点 clojure macro 记录与心得和大家分享,望指正. (clojure 官网 https://clojure.org/ 值得反复看)

首先要理解宏的基础,为什么只有lisp系的语言才有宏? 三个字 同像性 .
https://clojure.org/reference/reader

Clojure is a homoiconic language, which is a fancy term describing the fact that Clojure programs are represented by Clojure data structures. This is a very important difference between Clojure (and Common Lisp) and most other programming languages - Clojure is defined in terms of the evaluation of data structures and not in terms of the syntax of character streams/files. It is quite common, and easy, for Clojure programs to manipulate, transform and produce other Clojure programs.

代码即数据,数据即代码
clojure 中的常用数据结构

Symbols
Literals
Lists
Vectors
Maps
Sets

其次 编译期 运行期 这两个时期要明白.
clojure的每一个函数(fn)都会编译成一个class类文件. 宏是一个被打了tag的函数. 在求值的时候产生的值被当做正式代码. (宏是用来产生代码的函数)

 defmacro  本身是一个fn 
 (. (var defmacro) (setMacro))
static Keyword macroKey = Keyword.intern(null, "macro");  //打的标记 
image.png

写宏的原则
不用宏是可以的.
能写成函数就不要用宏(因为写宏没有写函数简单直观,容易写错,需要先在 REPL 中测试一番)
只有不得不用时才用宏(性能要求高时比函数调用快,或者需要“代码<->数据”相互转换)
精心设计的宏调用比函数调用更 DSL(如实现控制结构、传递 Java方法)

以上是宏的理解关键之处. 接下来 我们再看几个难点 Macro characters
宏中使用简写符号(语法糖)

syntax-quote (`)(反引号)  里面才能使用 unquote  (~)  unquote-splicing (~@)
~  ~@ 必须要在 ` 之内. 不在其内.
就会报;Attempting to call unbound fn: #'clojure.core/unquote

`
原原本本地直译过去,不用`,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

~@
表示后面的symbol or form is list

Clojure ' `区别在于syntax-quote (`)会进行symbol的解析 (全限定名)
user=> '(foo bar)
(foo bar)
user=> `(foo bar)
(user/foo user/bar)

syntax-quote 将symbol解析成为fully-qulified symbol,所谓fully-qulified symbol 
就是形如namespace/name或fully.qualified.Classname 
如果是symbol是非名称空间限定的(non-namespace-qualified)且以#符号结尾,
会解析成为name_uniqueid的形式比如x_123.
注意:
syntaxQuote 经过一系列运算后,最后还是转化为了 quote 
static Object syntaxQuote(Object form) {
return ret = RT.list(Compiler.QUOTE, sym);
}
~ ~@ 必须在 `里面
`~'a 
~'idx  ;不在 syntax-quote中使用 则会报错.
`(+ a ~'idx)  ;(clojure.core/+ cfenxi.core-test/a idx)

'~x  显示变量名,即a
~x 解析为变量值,即a的值 10  

一个递归查看 字符串 数据 与 代码关系的代码

(ns cfenxi.core-test
 (:require [clojure.test :refer :all]
           [cfenxi.core :refer :all]
           [clojure.walk :as w])
 (:import (clojure.lang Compiler$C))
 )
(defn study-read
 "Lisp reader 的时候,会把字符 根据规则解析成 data 具体类型是 java 定义的.
 Symbol PersistentList String MapEntry PersistentArrayMap
 Keyword PersistentList
 "
 [str]
 (let [r (read-string str)]
  (w/prewalk (fn [x] (prn x (type x)) x) r)
  ;(w/prewalk-demo r)
  )
 )
(study-read "(+ 3 2)")
(study-read "(fn [x] (do {:a x}))")

Loading test/cfenxi/core_test.clj... 
(+ 3 2) clojure.lang.PersistentList
+ clojure.lang.Symbol
3 java.lang.Long
2 java.lang.Long
(fn [x] (do {:a x})) clojure.lang.PersistentList
fn clojure.lang.Symbol
[x] clojure.lang.PersistentVector
x clojure.lang.Symbol
(do {:a x}) clojure.lang.PersistentList
do clojure.lang.Symbol
{:a x} clojure.lang.PersistentArrayMap
[:a x] clojure.lang.MapEntry
:a clojure.lang.Keyword
x clojure.lang.Symbol
clojure2 miss chang

相关文章

  • clojure macro 宏的一点浅见

    工作之余 站在半山腰 清风吹来, 大西北干燥的凛冽,似乎要吹进骨子里,心中升起一种印在灵魂深处的无法言说的亲切感....

  • Clojure macro

    At first, I want to add before/after to FacthCheck(Julia ...

  • clojure宏魔法

    了解clojure的宏(macro)之后,真真是个好东西呀。让你可以随心所欲,设计自己的语法,甚至创造新的语言。而...

  • 宏(Macro)指的是 Rust 中一系列的功能 声明(Declarative)宏, 使用macro_rules!...

  • 模板宏

    声明宏 {% macro 宏的名字(参数) %}​内容{% endmacro %} 调用宏 {{ 宏的名字(参数...

  • clojure 宏

    宏的本质是fn* 函数. 该函数有个meta 说明是宏. 则clojure compiler 在编译的时候需...

  • 数据分析师-Week16

    1.调用rar解压.rar 2.在宏(macro)中高亮显示关键字 3.用宏macro处理参数并返回结果

  • JS事件循环机制之宏任务/微任务

    宏任务(macro-task)macro-task.png 微任务(micro-task)micro-task.p...

  • 宏指令(Macro)

    人类宇宙,克莱因瓶 衡宇宙,克莱因瓶 量子计算机,瓶塞 瓶外,无限 无限侵入有限时空, 所以我们将历经无数种可能 ...

  • this.$nextTick的那些事

    宏任务macro task: setTimeout、MessageChannel、postMessage、setI...

网友评论

      本文标题:clojure macro 宏的一点浅见

      本文链接:https://www.haomeiwen.com/subject/muwmxdtx.html