Clojure 基于函数的流程控制






repeatedly 字面意思为重复函数。一般的用法如下:


  1. user=> (repeatedly

    5

    #(rand-

    int


    11

    ))

  2. (

    6


    8


    2


    6


    6

    )


重复产生5次随机数。rand-int 11表示0至11的随机数。


这里顺便提一下repeat函数:repeat函数接受一/两个常量参数,用法如下:


  1. user=> (repeat

    5

    (

    int

    (rand-

    int


    100

    )))

  2. (

    30


    30


    30


    30


    30

    )


当repeat、repeatedly函数只接受一个参数时(即没有重复次数的参数),需要配合take来中止,否则会产生内存溢出的错误。如下:


  1. user=> (repeatedly #(rand-

    int


    11

    ))

  2. OutOfMemoryError Java heap space  java.util.Arrays.copyOf (Arrays.java:

    2882

    )

  3. user=> (take

    5

    (repeatedly #(rand-

    int


    11

    )))

  4. (

    10


    7


    0


    2


    8

    )





iterate:





迭代函数形式如下:




(iterate f v)




相当于:




while(true) { v = f(v) }




所以一般要配合(take n sequence)来中止:


  1. user=> (take

    10

    (iterate inc

    5

    )) ; (

    5


    6


    7


    8


    9


    10


    11


    12


    13


    14

    )

  2. user=> (take

    10

    (iterate #(+ %

    5

    )

    5

    )) ; (

    5


    10


    15


    20


    25


    30


    35


    40


    45


    50

    )

  3. user=> (take

    10

    (iterate #(* %

    2

    )

    2

    )) ; (

    2


    4


    8


    16


    32


    64


    128


    256


    512


    1024

    )




基于序列的流程控制






dotimes 会执行给定的表达式一定次数, 一个本地binding会被给定值:从0到一个给定的数值。如下:


  1. user=> (dotimes [num

    3

    ] (println

    "number:"

    (inc num)))

  2. number:

    1


  3. number:

    2


  4. number:

    3


  5. nil




doseq和for的语法是一样的,只不过for返回lazy seq而doseq接受任意数量的表达式, 以有副作用的方式执行它们, 并且返回nil


  1. user=> (doseq [i (range

    10

    )] (println i))


  2. 0



  3. 1



  4. 2



  5. 3



  6. 4



  7. 5



  8. 6



  9. 7



  10. 8



  11. 9


  12. nil

  13. user=> (doseq [i [

    1


    2


    3

    ] j [

    10


    20

    ]] (println i

    "-"

    j))


  14. 1

    -

    10



  15. 1

    -

    20



  16. 2

    -

    10



  17. 2

    -

    20



  18. 3

    -

    10



  19. 3

    -

    20


  20. nil




for、doseq都支持遍历多个集合(最右边的最快),同时还可以用:when 和 :while来过滤。


  1. user=> (

    for

    [x (range

    3


    7

    )] (* x x))

  2. (

    9


    16


    25


    36

    )


  3. user=> (

    for

    [x [

    0


    1


    2


    3


    4


    5

    ] :let [y (* x

    3

    )] :when (even? y)] y)

  4. (

    0


    6


    12

    )


上面第二条语句可理解为:先定义x为集合,再使用let将y赋值为x*3,最后判断y是否为偶数,偶数才返回