clojure 宏_学习Clojure:arrow和doto宏

clojure 宏

对我来说,学习一门新语言就像进海:一次只脚趾。

这是在学习Clojure的焦点series.Other职位包括第三职位:

  1. 解码Clojure代码,让您不知所措
  2. 学习Clojure:应对动态打字
  3. 学习Clojure:arrow和doto宏 (本文)
  4. 学习Clojure:动态调度
  5. 学习Clojure:依赖类型和基于合同的编程
  6. 学习Clojure:与Java流进行比较
  7. 关于学习Clojure的反馈:与Java流进行比较
  8. 学习Clojure:换能器

本周,我们将看一些强大的宏。

问题

当您不习惯Clojure时,括号有时会削弱代码的可读性。

(- 25 (+ 5 (* 3 (- 5 (/ 12 4)))))

上述片段的Kotlin等效项为:

25-(5+(3*(5-(12/4))))

显然,它与Clojure或括号都不相关。 让我们使用“数据管道”重新整理上面的Kotlin代码段,以提高可读性:

4.let { 12 / it }
 .let { 5 - it }
 .let { 3 * it }
 .let { 5 + it }
 .let { 25 - it }

解决方案

我敢肯定,以顺序方式呈现处理可以大大提高可读性,尤其是随着操作数量的增加。 Clojure是否可以提供相同的顺序处理功能不是很好吗? 幸运的是,它使用了特定的

(->> 4     (1)
  (/ 12)   (2)
  (- 5)    (2)
  (* 3)    (2)
  (+ 5)    (2)
  (- 25))  (2)
  1. 从这个值开始
  2. 应用功能并将上一行的结果作为最后一个参数

与Kotlin相比,唯一的结构差异是it参数是隐式的 ,并且用作最后一个参数。

->>是一个 ,称为thread-last宏

巨集

Clojure具有程序化的宏系统,该系统允许用户代码扩展编译器。 宏可用于定义语法构造,这需要其他语言的原语或内置支持。 实际上,Clojure的许多核心构造不是基元,而是普通的宏。

— Clojure文档
https://clojure.org/reference/macros
宏是非常强大的语言构造,无论是Clojure还是其他语言。 谨慎而明智地使用它们,可以使某些代码摘录更易于阅读和编写。 在其他情况下,它们可以比说“宏”更快地破坏代码库的可读性。 在创建自己的模型之前,请务必谨慎并考虑它。

Clojure宏的macroexpand可以通过macroexpand函数解释它们。 结合REPL,它是开发人员手中的绝佳工具。 例如,让我们使用macroexpand检查上面代码的结果:

(macroexpand '(->> 4      (1)
                (/ 12)
                (- 5)
                (* 3)
                (+ 5)
                (- 25)))
  1. 圆括号前的单引号可防止Clojure将其解释为表达式的开始,而不是一个集合。

如预期的那样,它产生:

=> (- 25 (+ 5 (* 3 (- 5 (/ 12 4)))))

更多宏

Clojure中有大量可用的宏。 其中,有些与上面的thread-last宏密切相关:

线程优先

->>宏将前一个表达式的结果用作最后一个参数,而线程优先->将其用作第一个参数。 根据预期的类型,它可以:

  • 由于类型不匹配而阻止代码运行
  • 更改返回的结果
  • 保持相同的结果( 用于交换函数,例如加法)

例如,让我们将以上代码片段的thread-last宏更改为thread-first,然后检查每一行的结果:

(-> 4
  (/ 12)   (1)
  (- 5)    (2)
  (* 3)    (3)
  (+ 5)    (4)
  (- 25))  (5)
  1. 1/3
  2. -14 / 3N
  3. -14N
  4. -9N
  5. -34N
去做

在上面的示例中,箭头函数(或线程函数)与let相似。 它们都应用函数并返回结果-唯一的区别是隐式参数的位置。 尽管Clojure是一种功能编程语言,但有时还是需要处理可变引用。 通常,与Java集成时就是这种情况。

在Kotlin中,将使用apply函数; 在Clojure中,等效项是doto

(doto (HashMap.)
  (.put :a "Alpha")
  (.put :b "Beta"))    (1)
  1. {:b "Beta", :a "Alpha"}

使用macroexpand显示最终形式:

(macroexpand '(doto (HashMap.)
  (.put :a "Alpha")
  (.put :b "Beta")))

(let* [G__1755 (HashMap.)]    (1)
  (.put G__1755 :a "Alpha")   (2)
  (.put G__1755 :b "Beta")    (2)
  G__1755)                    (3)
  1. 在随机引用名称下创建HashMap的新实例
  2. 将数据放入地图
  3. 返回地图

结论

在本文中,我们看到了一些特定的宏,这些宏在开发过程中非常有用。 箭头功能类似于Kotlin的let ,而doto是类似的apply

更进一步:

翻译自: https://blog.frankel.ch/learning-clojure/2/

clojure 宏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值