About me

我的照片
目前就职于杭州某电子商务公司,工作兴趣包括高并发分布式架构,JVM性能优化等方面。

2012年8月10日星期五

clojure基本知识记录

最近在学习clojure,一种JVM上的lisp方言。在这里记录一下clojure的基本知识。
======================================

symbol
  符号绑定到不可变值。可理解为引用。
  Clojure没有变量。
  (symbol? aaa) 判断是否是符号
  
list
  形式
  用途:
    函数调用
 macro
 special form
 
list
  list (list 1 2 3)
  语法糖 '(1 2 3)
  first (first '(1 2 3)) => 1
  rest (rest '(1 2 3)) => (2 3)
  
vector
  [1 2 "three"]
  下标求值  ([7 8 9] 2) => 9
  vector自己作为运算符
  
map
  {"a" 1, "b" 2, "c" "aaa"}
  按key求值  (get {"a" 1, "b" 2, "c" "aaa"} "c") => "aaa"
  语法糖 ({"a" 1, "b" 2, "c" "aaa"} "c") => "aaa"
  第三种形式 (:a {:a 1, :b 2, :c 3}) => 1
  
def
  bind symbol to value
  clojure没有变量,但是symbol的绑定可以修改。
  (def x 5) => #'JiurenTest/x
  x => 5
  (def x 9) => #'JiurenTest/x
  x => 9
  
defn = def + fn
  定义函数 (defn add1
             [x]
             (+ x 1))
  函数名是一个symbol
  参数列表是一个vector
  defn是一个macro. def + fn
  正规形式,(def funcName 
              (fn [argList...]
       (body)))
  fn定义匿名函数,lambda函数
  
  (fn? +) => true 判断是否是函数
  (fn? add1) => true   add1函数作为fn?的参数
  (fn? fn?) => true
  
doc
  查看doc  (doc xxx)
  返回值nil,输出是副作用。
  (defn add1
    "add argument by one"
    [x]
    (+ x 1))
  
str
  创建string的函数
  (fn? str) => true
  (str) => ""
  (str xxx) 类似于 xxx.toString()
  (str +) => "clojure.core$_PLUS_@14627a"
  (str 1 2) => "12"  拼接
  
if
  (if true "yes") => "yes"
  (if false "yes") => nil   else分支默认值为nil
  (if (= 1 2) 5 10) => 10
  (if 0 true) => true
  (if "" true) => true
  (if nil "yes" "no") => "no"
  非boolean值转boolean值,nil转为false,其他转为true

do
  顺序执行 (do (expression)*)  返回最后一个表达式的值
  (do (println "Hello.") (+ 2 2))
    Hello.
 4
  
when
  没有else分支。if分支可以有多个expression
  when是一个宏。when = if + do
  (when true 1 2 3) => 3
  (when false 1 2 3) => nil
  
let
  创建临时symbol。类似于局部变量。
  (fn? let) 发现let貌似也是一个宏。???
  (let [x 2] (+ x 8)) => 10
  (let [x 2 y 8] (= (+ x y) 10)) => true

loop
  (loop [bindings*] exprs*)
  和let只有一点不同,在开始处设置了回归点。see recur.
  也就是说,如果内部没有recur的话,就没有循环。
  (loop [i 0]
    (when (< i 5)
   (println "i:" i)
   (inc i)))
  => 1
  输出:
  i: 0
  
recur
  (recur exprs*)  exprs个数和loop中的bindings个数相同
  Evaluates the exprs in order, then, in parallel, rebinds the bindings of the recursion point to the values of the exprs. If the recursion point was a fn method, then it rebinds the params. If the recursion point was a loop, then it rebinds the loop bindings. Execution then jumps back to the recursion point. 
  
  Note that recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization and the use of self-calls for looping of unknown bounds is discouraged. recur is functional and its use in tail-position is verified by the compiler.
  
  计算 + 重新绑定 + goto
  (loop [i 0]
    (when (< i 5)
   (println "i:" i)
   (recur (inc i))))
  => nil
  输出:
    i: 0
    i: 1
    i: 2
    i: 3
    i: 4

  从后向前
  (defn factorial [n]
    (loop [i n acc 1]
   (if (= i 1)
     acc
  (recur (dec i) (* i acc)))))
  从前向后
  (defn factorial2 [n]
    (loop [i 2 acc 1]
   (if (> i n)
     acc
  (recur (inc i) (* i acc)))))

sequence
  Seqs differ from iterators in that they are persistent and immutable, not stateful cursors into a collection. 
  
发现
  高阶函数体现出: code as data
  clojure的expression都是嵌套的,因此执行过程是栈式的。

没有评论:

发表评论