zoukankan      html  css  js  c++  java
  • Clojure语法学习-循环

    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]

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

  • 相关阅读:
    快速掌握麦肯锡的分析思维
    如何建立数据分析的思维框架
    《七周数据分析师》-万字总结
    装饰器
    迭代器&生成器
    Excel 怎样去掉单元格中的回车符号
    python面试题(一)
    Python基础5
    Python基础4
    Python enumerate() 函数
  • 原文地址:https://www.cnblogs.com/devos/p/4207707.html
Copyright © 2011-2022 走看看