Clojure 基础

1. Forms

 

 

FormExample(s)
Booleantrue,false
Charactor\a
Keyword:tag,:doc
List(1,2,3),(println "foo")
Map{:name “Bill", :age 50}
Nilnil
Number1,4.2
Set#{:snap :crackle :pop}
String"hello"
Symboluser/foo,java.lang.String
Vector[1 2 3]

 

数值类型

 42

     42

 [1 2 3]

     [1 2 3]

 (+ 1 2)

     (3)

(concat [1 2] [3 4])

     (1 2 3 4)

(+ 1 2 3 )

     (6)

(+)

      0

(- 10 5)

      5

(* 3 10 10)

      300

(> 5 2)

      true

(>= 5 5)

      true

(< 5 2)

      false

(= 5 2)

      false

(/ 22 7)

      22/7

(class (/ 22 7))

      clojure.lang.Ratio

(/ 22.0 7)

      3.142857142857143

(quot 22 7)

      3

(rem 22 7)

      1

(+ 1 (/ 0.0001 1000000000000000000))

      1.0
(+ 1 (/ 0.0001M 1000000000000000000)) ;;BigDecimal
      1.00000000000000000000001M
(class (* 1000 1000 1000))
      java.lang.Integer
(class (* 1000 1000 1000 1000 1000 1000 1000 1000))
      java.math.BigInteger

标识符(Symbols)
如:+,concat,java.lang.String 都是symbols
  符号名称定义一件事。
1.函数:如str,concat
2.操作符:如+,-
3.命名空间:clojure.core,java.lang
4.数据结构及引用

字符串及字符
"This is a\nmultiple string"
     "This is a\nmultiple string"

(println "a\nb\nc")
     a
     b
     c
     nil

(.toUpperCase "hello") ;; 这个点说明,是调用的Java 方法,而不是Clojure函数
    "HELLO"

(str 1 2 nil 3) ;; str 是toString的Clojure实现。会跳过nil,而不会报错
    "123"


字符是 java characters,语法变为\{letter},如\h \hi
(str \h \e \y \space \y \o \u)
    "hey you"

(Character/toUpperCase \s)
    \S

(interleave "hi" "mix")
    \h\m\i\i

(str (interleave "hi" "mix"))
   "clojure.lang.LazySeq@627a81b9"

使用apply 函数,来获得字符串.(apply f args* argseq)
(apply str (interleave "hi" "mix"))
   "hmii"
(apply str (take-nth 2 "hi mary , where to go"))
   "h ay,weet o"

 

Boolean 和 Nil

(if nil "true" "false");; nil 代表 false

 

    "false"

 

 

(if () "We are in Clojure!" "We are in Common Lisp!") ;; List programmers be warned, empty list is true

   "We are in Clojure!"

 

(if 0 "zero is true" "zero is false");; C Programmers be warned:zero is not false in Clojure

    "zero is true"

断言函数

(true? expr)

(false? expr)

(nil? expr)

(zero? expr)

(true? true)

    true

(true? "foo")

    false

(zero? 0.0)

    true

(zero? (/ 22 7))

    false

 

Clojure有很多断言,通过(find-doc #"\?$")在REPL中查看

Maps, Keywords, and Structs

(def inventors {"Lisp" "McCarthy" "Clojure" "Hickey"})
    #'user/inventors

(def inventors {"Lisp" "McCarthy", "Clojure" "Hickey"})
    #'user/inventors

 

(inventors "Lisp") ;; Maps 是一个函数

     "McCarthy"

 

 

(get a-map key not-found-val?) ;; 获得Map的Value,如没有此Key,会返回一个自己定义的值。

 

 

(get inventors "Lisp" "I dunno!")

     "McCarthy"

(get inventors "Foo")

     "I dunno!"

 

Keyword 很像标识符,但需要在标识符前面加一个“:”,keyword会自己解释自己

:foo

    :foo

 foo

    CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0) 

 

一般,把keyword做为Map的key

 

(def inventors {:Lisp "McCarthy" :Clojure "Hickey"})

    #'user/inventors

 

 

(inventors :Clojure)

    "Hickey"

(:Clojure inventors) ;; keyword 是一个函数

    "Hickey"

 

 

(defstruct name & keys) ;; 一个名称,对应多个keys,即定义keys

(defstruct book :title :author)

    #'user/book

 

(struct name & vals);; map对应的多个值

(def b (struct book "Anathem" "Neal Stephenson"))

   #'user/b

b
   {:title "Anathem", :author "Neal Stephenson"}

(:title b)
   "Anathem"

(struct-map name & inits);;初始化Maps及添加新的key&value对
(struct-map book :copyright 2008 :title "Anathem")
     {:title "Anathem", :author nil, :copyright 2008}

2.Reader macros

Reader MacroExample(s)
Anonymous function#(.toUpperCase %)
Comment;single-line comment
Deref@form=>(deref form)
Meta^form =>(meta form)
Metadata#^metadata form
Quote'form => (quote form)
Regex pattern#"foo" => a java.util.regex.Pattern
Syntax-quote`x
Unquote~
Unquote-splicing~@
Var-quote#`x => (var x)


3.Funcitons

(str "hello" " " "world") ;一个函数仅仅是一个list,第一个元素是函数名

    "hello world"

 

定义函数

(defn name doc-string? attr-map? [params*] body)

 

 

(defn greeting

"Returns a greeting of the form 'Hello, username.'"

[username]

(str "Hello, " username))


(greeting "foo")
    "Hello, foo"

(greeting)
     ArityException Wrong number of args (0) passed to: user$greeting  clojure.lang.AFn.throwArity (AFn.java:437)

定义函数,可以有多个body
(defn name doc-string? attr-map? ([params*] body)+ )

(defn greeting
"Returns a greeting of the form 'Hello, username.'
Default username is 'world'."

([] (greeting "world"))
([username] (str "Hello, " username)))
    #'user/greeting

(greeting)
     "Hello, world"

(defn date [person-1 person-2 & chaperones] ;& arity
(println person-1 "and" person-2
"went out with" (count chaperones) "chaperones." ))
(date "Romeo" "Juliet" "Friar Lawrence" "Nurse")
| Romeo and Juliet went out with 2 chaperones.


Anonymous Functions
1)匿名函数很简单,可以自己解释自己,给一个名字会很难读;
2)匿名函数只需要在内部访问,不需要外部访问;
3)匿名函数需要访问创建他的函数的数据;

(defn indexable-word? [word]
(> (count word) 2))
(use '[clojure.contrib.str-utils :only (re-split)])
(filter indexable-word? (re-split #"\W+" "A fine day it is" ))
-> ("fine" "day" )

(fn [params*] body);匿名函数定义

(filter (fn [w] (> (count w) 2)) (re-split #"\W+" "A fine day"))
    ("fine" "day")

匿名函数简写:(#body)
参数使用%1,%2,%...
(filter #(> (count %) 2) (re-split #"\W+" "A fine day it is"))
    ("fine" "day")

(defn indexable-words [text]
(let [indexable-word? (fn [w] (> (count w) 2))]
(filter indexable-word? (re-split #"\W+" text))))

(indexable-words "a fine day it is")
    ("fine" "day")

返回函数实例
(defn make-greeter [greeting-prefix]
(fn [username] (str greeting-prefix ", " username)))

(defn make-greeter [greeting-prefix]
(fn [username] (str greeting-prefix ", " username)))

(def hello-greeting (make-greeter "Hello"))
    #'user/hello-greeting

(def aloha-greeting (make-greeter "Aloha"))
    #'user/aloha-greeting

(hello-greeting "world")
    "Hello, world"

(aloha-greeting "world")
    "Aloha, world"

((make-greeter "Howdy") "pardner")
    "Howdy, pardner"

什么时候使用匿名函数
    使code可读性好,不会被做为公共的函数调用。建议多多使用匿名函数。

4.Bindings and namespaces

Bindings
(defn triple [number] (* 3 number))
    #'user/triple
(triple 10)
    30

(let [bindings*] exprs*)
(defn square-corners [bottom left size] 
  (let [top (+ bottom size)
     right (+ left size)]
[[bottom left] [top left] [top right] [bottom right]]))
    #'user/square-corners
(square-corners 10 10 10)
    [[10 10] [20 10] [20 20] [10 20]]

Destructuring
(defn greet-author-1 [author]
(println "Hello," (:first-name author)))

(greet-author-1 {:last-name "Vinge" :first-name "Vernor"})
    Hello, Vernor

(defn greet-author-2 [{fname :first-name}];argument bind fname to the :first-name
    (println "Hello," fname))
(greet-author-2 {:last-name "Vinge" :first-name "Vernor"})
    Hello, Vernor

(let [[x y :as coords] [1 2 3 4 5 6]]
(str "x: " x ", y: " y ", total dimensions " (count coords)));:as clause gives you a binding for the entire enclosing structure
      "x: 1, y: 2, total dimensions 6"

Namespace
(resolve sym)
(resolve 'foo)
    #'user/foo

(in-ns name); 切换Namespace

(in-ns 'myapp)

(String)
  java.lang.String
(clojure.core/use 'clojure.core); 导入clojure.core函数

File/separator
java.lang.Exception: No such namespace: File

 java.io.File/separator
    "/"


(import '(java.io InputStream File));Once you import a class, you can use its short name


(require 'clojure.contrib.math)
(clojure.contrib.math/round 1.7)
2
(round 1.7)
java.lang.Exception:
Unable to resolve symbol: round in this context

(use 'clojure.contrib.math);refer all public vars in clojure.contrib.math
nil

(use '[clojure.contrib.math :only (round)]);:only避免方法冲突
nil

(use :reload '[clojure.contrib.math :only (round)]);包文件有变化时,使用:reload

(use :reload-all 'examples.exploring);

(ns name & references);the ns macro sets the current namespace to name &references 可以是:import,:require,:use

(ns examples.exploring
(:use examples.utils clojure.contrib.str-utils)
(:import (java.io File)))


(find-doc "ns-"); for help

def定义值或名称
 (def v1 10)
   (def v2 (int 10)); 定义成基本类型,在循环计算中可以提高效率
   (def v3 (fn [n] (* n n ))); v3是函数别名

let定义临时变量
局部临时变更定义:
(let [x 10] ( println x))
定义多个变量(def 不能定义多个)
 (let [[x y] [3 4]] (println (* x y))); 
 (let [x 3 y 4 ] (println (* x y )))
 (let [[x y] [3 4 5]] [x y]);[3 4]
 (let [[_ _ z] [3 4 5]] z); 5
 (let [[ a b & c] [1 2 3 4 5]] [a b c]); [1 2 (3 4 5)]
多个变量之间可以依赖(后面的依赖前面的),这点非常非常有用:
(let [x 10 y ( * x x ) z (* 2 y)] (println z)); 200
let 的执行体内可以调用多个函数:
  (let [x 10] (println x) (println (* x x )))

binding可以临时改变def定义的变量:
 (def v1 10)
 (def v2 20)
 (binding [v1 1 v2 2] (+ v1 v2));3
 (+ v1 v2); 30
 (defn f [] (+ v1 v2))
 (binding [v1 1 v2 2] (f)); 3
 (f); 30

5.Flow control

if,do, and loop/recur

 

 

(defn is-small? [number]

(if (< number 100) "yes" ))


 

(is-small? 50)

    "yes"

 

 

(is-small? 50000)

    nil

 

 

(defn is-small? [number]

(if (< number 50) "yes" "no"))

    #'user/is-small?

(is-small? 50000)

    "no"



(defn is-small? [number]
(if (< number 100)
"yes"
(do
(println "Saw a big number" number)
"no" )))

(is-small? 100)
    Saw a big number 100 ; side effect
    "no"

Recur with loop/recur
(loop [bindings *] exprs*)

(recur exprs*)

 (defn testloop []
(loop [result [] x 5]
(if (zero? x) 
result
(recur (conj result x) (dec x)))))
    #'user/testloop
 (testloop)
    [5 4 3 2 1]

(defn countdown [result x]
(if (zero? x)
result
(recur (conj result x) (dec x))))
    #'user/countdown
(countdown [] 10)
    [10 9 8 7 6 5 4 3 2 1]


(into [] (take 5 (iterate dec 5)))
    [5 4 3 2 1]
(into [] (drop-last (reverse (range 6))))
    [5 4 3 2 1]
(vec (reverse (rest (range 6))))
    [5 4 3 2 1]


6.Metadata

metadata是关于数据的数据

 

(with-meta object metadata)



=======================================================
代码块:do
(do
  (println "hi")
  (apply * [ 2 3 4 ])
)
  hi
  24

fn let loop try defn 隐含使用do表达式

定义变量 vars: def
(def p "foo")

其它定义defn defn- defprotocol defonce defmacro deftype defrecord defmethod

local 绑定: let
(defn hypot
      [x y]
      (let [x2 (* x x)
              y2 (* y y)]
      (Math/sqrt (+ x2 y2))))


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值