do和块语句

在Scala中,花括号{}括起来的语句构成一个block,它的值就是最后一个语句的值。

scala> val a = {| println("a")| 1}
a
a: Int = 1

{println("a"); 1}的值为1。

在Clojure中,有时需要使多个form组成一个block, 这个block的值是最后一个form的值。这时候就用do

user=> (def a (do (println "a") 1))
a
#'user/a
user=> a
1

do takes any number of forms, evaluates them all, and returns the last.

do接受任意多的form作为参数,对它们分别求值,然后返回最后一个form的值。

循环

有哪些要素才能构成一个循环?

在Java中

  1. 首先,我们需要提供一个在每次循环中都会被执行的语句——循环体
  2. 如果不是无限循环,我们需要提供退出条件,当这个条件满足时,不再循环。

在Clojure中

  1. 首先,我们需要提供一个在每次循环中都会被执行的语句——循环体
  2. 我们需要提供循环条件。它这个条件满足时,继续下一次循环。

也就是说Java需要我们告诉它什么时候退出循环,而Clojure需要我们告诉它何时继续循环。

Java的for循环是这样的

for(int i = 0; i < 10; i++)System.out.println(i);

可以认为 i< 10, i++以及System.out.println(i)构成了循环体。退出条件为i<10。

while循环与for循环的不同之处在于while无法声明只在循环内部使用的变量。在上边的for循环中, i只在循环内部使用。如果我们想让while有类似的功能(当然,while没这功能),那么while需要接受一个初始化语法,变成

while(int i = 0)(i < 10){println(i);i++;
}

在Clojure中,同样可以以binding的形式提供初始化语句, 以及提供循环体。这通过loop这种form来实现

(loop [bindings *] exprs*)

这就类似前边这个加强版的while。同时,在while循环中需要break来打破循环; 在Clojure中,我们需要一种form来继续循环,这就是recur。可以认为Java的循环是主动的,而Clojure中的是被动的,你必须在代码中驱动它前进。

(loop [a 0] (if (< a 10) (do (println a) (recur (+ 1 a)))))

  recur使得程序重新开始执行loop。但是如何程序中是简单地重新执行loop,它就只是原地踏步,因为所有的绑定都始终是初始值。所以recur不仅转变了程序的执行流,而且修改了loop开始的绑定。即,recur使得loop开始对a的绑定变成了(+ 1 a)。

假如,我们在loop开始的时候多提供一个绑定

(loop [a 0 b 1] (if (< a 10) (do (println a) (recur (+ 1 a)))))

  REPL就会告诉我们提供给recur的参数个数不对

CompilerException java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 2 args, got: 1

实际上,recur不仅可以用于loop,也可以用于函数,它使得函数被重新执行。

举个书上的例子

(defn countdown [result x] (if (zero? x)
result
(recur (conj result x) (dec x))))

执行(count down [] 5)会输出返回值[5 4 3 2 1]

这种代码怎么看着这么眼熟呢?这不就像是尾递归吗?

转载于:https://www.cnblogs.com/devos/p/4207707.html

Clojure语法学习-循环相关推荐

  1. 2021年大数据常用语言Scala(八):基础语法学习 循环

    目录 循环 for表达式 while循环 循环 在scala中,可以使用for和while,但一般推荐使用for表达式,因为for表达式语法更简洁 for表达式 语法 for(i <- 表达式/ ...

  2. Python基础语法学习笔记

    Python基础语法学习笔记 想淘宝省钱看我简介,博客www.liangxin.name (一) 一.Print()函数 1.数字可以直接输出,无需加引号 只能理解数字,却读不懂文字.因为数字和数学运 ...

  3. [转]verilog语法学习心得

    verilog语法学习心得 1.数字电路基础知识: 布尔代数.门级电路的内部晶体管结构.组合逻辑电路分析与设计.触发器.时序逻辑电路分析与设计 2.数字系统的构成: 传感器  AD  数字处理器  D ...

  4. python语法学习—实现猜拳游戏

    python基础语法学习,通过实现猜拳游戏,来对python语法的学习. # python语法实现 猜拳游戏 电脑随机出拳进行比较,用户自己输入要出的拳,用户赢了就退出游戏 # 主要用到 python ...

  5. P4 程序设计语法学习

    P4语法学习 P4程序模板 #include<core.p4> #include<v1model.p4> /* HEADERS */ struct metadata { ... ...

  6. MySQL语法学习笔记

    MySQL语法学习笔记 学习之道,非尽心竭力者不能进也!我是小七黛,欢迎查看我的笔记,有问题欢迎交流探讨. SQL是一种结构查询语言,用于查询关系数据库的标准语言,包括若干关键字和一致的语法,便于数据 ...

  7. ninja文件语法学习

    ninja文件语法学习 ninja本质上是配置文件,没有分支,循环的流程控制. 语法 基本概念 edge(边):build语句,可以指定目标(target)输出(output).规则(rule)与输入 ...

  8. Go基础语法学习总结

    Go基础语法学习总结 一.基础语法 1.常见数据类型 数据类型包括有:布尔类型.字符串类型.数字类型(整型.浮点型.复数等).派生类型(数组类型.slice 切片类型.map 集合类型.struct ...

  9. Verilog HDL 语法学习笔记

    今天给大侠带来Verilog HDL 语法学习笔记,话不多说,上货. 关于详细的VHDL语法以及Verilog HDL语法可参见往期文章. 一周掌握 FPGA VHDL Day 7 暨汇总篇 一周掌握 ...

最新文章

  1. python怎么读excel文件-Python读写Excel文件方法介绍
  2. go语言有哪些劣势?
  3. 经典算法复现!(条件随机场)CRF原理及实现代码
  4. 算法题12 数组中所有的逆序对
  5. java downloadfile_FileDownload.java:文件下载工具类
  6. php实例新讲php,实例讲解PHP5 新特性
  7. Asp.net MVC3 Razor语法小记
  8. HCIE Secuirty 防火墙内容安全组合 备考笔记(幕布)
  9. 【原创】大叔经验分享(26)hive通过外部表读写elasticsearch数据
  10. 树莓派64位系统_玩转树莓派之安装系统
  11. Web存储(Web Storage)介绍
  12. ad怎么修改栅格_AD18怎么改变pcb原理图的网格大小
  13. BXP千兆无盘网吧解决方案(转)
  14. springcloud学习-Eureka、Eureka高可用集群、Ribbon客户端负载均衡策略
  15. [BZOJ5276] Skyfall [CF235E] Number Challenge [莫比乌斯反演]
  16. 微信去除 防欺诈盗号请勿支付或输入qq密码 以及 防欺诈或盗号请不要输入qq密码 的方法
  17. pcm数据编码成为aac格式文件(可以在酷狗播放)
  18. markdown转html格式
  19. Java实现网络通信(TCP程序设计)
  20. python高级教程-2

热门文章

  1. 从介质部署额外域控制器
  2. 模态对话框和非模态对话框的消息循环
  3. CCNA的全套标准实验
  4. linux 查看ftp账户,linux的ftp服务之本地访问浏览与虚拟账户
  5. 模拟浏览器自动化测试工具Selenium之六设置代理篇
  6. VC6.0制作OCX并web调用
  7. Leetcode 127. 单词接龙 解题思路及C++实现
  8. 数据结构源码笔记(C语言):置换-选择算法
  9. 爬虫分类——通用网络爬虫、聚焦网络爬虫、增量式网络爬虫、深层网络爬虫
  10. 判断一个整数是否是水仙花数 || 编写程序,根据输入的月份和年份,求出该月的天数(1-12)|| 运算符的优先级问题 ||输出小写的a-z以及大写的Z—A||求出1-1/2+1/3-1/4…..1/