学无所长,一事无成
分类: Java
2015-07-02 18:02:49
a、双引号扩住
"hello clojure"
b、 字符串天然支持多行
"multiline strings
are very handy"
通过反斜线标识
a、普通字符:\h \e \l \l \o \space
b、特殊字符:\newline \formfeed \return \backspace \tab
求值成他们自身,经常被用来当做访问器来获取他们对应的值,如
(def person {:name "Sandra Crue" :city "Portland,ME"}) ;定义一个 map ;= #'user/person (:city person) ; 访问 person 的 :city 属性,关键字 :city 本身就是函数 ;= "Portland,ME" |
关键字始终以冒号 : 开头
关键字是一种命名类型,可以通过 name 、namespace 函数获取其名字和名字空间:
(name :user/location) ;= "location" (namespace :location) ;= nil |
符号也是一种标识符,其值是它所代表的 Clojure 运行时里面的那个值
(average[60 100 400]) ;= 160 |
average 就是一个符号,代表一个名叫 average 的 var 所指向的函数。
Clojure 里面把以 # 开头的字符串当做正则表达式:
(class #"(p|h)ail") ;= java.util.regex.Pattern
(re-seq #"(...) (...)" "foo bar") ;= (["foo bar" "foo" "bar"]) |
相关函数:re-seq、re-find、re-matches 以及 clojure.string 命名空间中定义的其他方法。
(read-string "(+ 1 2 #_(* 2 ) 8)") ;= (+ 1 2 8) |
(when true (comment (println "hello"))) ;= nil |
跟 #_ 不同的是,comment 不会被忽略,只是返回 nil。
单引号表示获取 Symbol 本身,而非其代表值。
Clojure 中使用列表来表示函数调用,因此通过添加一个单引号可阻止求值。
set 类似于枚举类型
命名空间是 Clojure 最基本的代码模块组件。所有的 Clojure 代码都是在一个命名空间中被定义和求值的。命名空间可以看成 Ruby 和Python 中的 module,Java 中的package。从本质上来说,命名空间是符号跟 vars 或者引入的 Java 类的一个映射关系。Clojure REPL 启动时默认的命名空间始终是 user。
Var 是 Clojure 中的一种引用类型,它是一种可修改的内存地址,从而可以保存任何值。在 var 被定义的命名空间里,var 和一个符号相关联,然后我们就可以通过这个符号来使用这个 var 。var 是用特殊形式 def 来定义的,def 只作用于当前命名空间。
个人备注:var 都是通过 def 来定义的,然后必定同某个 Symbol 关联,所以标量类型里面只有 Symbol 没有 var ,Symbol 就是用来引用 var 的。
(def x "hello") ;定义了一个 var ,同 Symbol x 关联 ;= #'user/x *ns* ;查看当前名字空间 ;= #<Namespace user> (ns foo) ;创建一个新的名字空间,并切换过去 *ns* ;= #<Namespace foo> user/x ;= "hello" x ;= Unable to resolve symbol: x in the contex .... |
当前的命名空间始终会绑定到 *ns*
Clojure 中的命名空间还负责维护符号和被引入 (import) 的Java 类之间的映射。
因为 java.lang 中的类默认被引入到每个 Clojure 命名空间中,所以可以直接访问这些 java 类。
同时,每个命名空间都会默认引入 Clojure 的核心库 clojure.core 中的所有 var,如 filter 函数等。
String ;= java.lang.String Integer ;= java.lang.Integer java.util.List ;= java.util.List java.net.Socket ;= java.net.Socket |
分析下 average 函数
(defn average [numbers] (/ (apply + numbers) (count numbers) ) ) |
根据"同向性",这些代码其实就是 Clojure 的数据结构。
看下 (average [60 80 100 400] ) 的运算过程。
这里符号 average 求值成它的 #'average,也就是当前命名空间中定义的那个函数。
传给它一个 vector,函数内部通过 numbers 来引用它。函数返回值传给 REPL ,REPL 将其输出到 stdout。
个人备注:解释下 #'average;我们知道 average (Symbol) -> var (内存指针) -> 函数体
因此 ' 阻止 average求值,得到一个 var ,再用 # 阻止var 求值,就得到了函数体。函数体放入 ( ) 就可以进行运算。