Clojure的学习笔记(二)

Metadata

identical? 和 java 中的 == 运算符是一个意思。= 和 java 中的 equal 函数是一个意思。

Metadata在Clojure中可以不改变数据的情况下给数据增加metadata,使用with-meta宏和meta宏

(def stu {:name "Stu" :email "stu@thinkrelevance.com"})
(def serializable-stu (with-meta stu {:serializable true}))

那么取数据的结果如下:

(meta stu)
 nil
(meta serializable-stu)
 {:serializable true}

可以用 ^ 代替 meta 来完成上面的工作

当我们根据一个老对象创建一个新对象的时候,老对象的metadata就会跟随着来到新对象这里。

metadata 可以用来给一个函数指定参数和返回值类型,这在传统的函数式编程中往往是没有的,这点缺失也往往成为函数式语言不适合调试的明证。很幸运的是Clojure通过metadata提供了类似的能力。

比如下文我们定义了一个函数,这个函数的参数和返回值都是String类型的:

(defn #^{:tag String} shout [#^{:tag String} s] (.toUpperCase s))

由于metadata的tag参数太常用,在Clojure中可以简化为下面这个形式:

(defn #^String shout [#^String s] (.toUpperCase s))

这样,当你用一些不是String的参数来调用shout的时候就会爆出下面的错误:

(shout 1)
java.lang.ClassCastException: \ 
java.lang.Integer cannot be cast to java.lang.String

如果你觉得这样定义的函数看起来有点怪异,那么便可以把这个metadata的定义放到最后来做,不过与普通的函数定义有区别的地方在于,我们要用括号包裹起函数体:

(defn shout 
    ([s] (.toUpperCase s)) 
    {:tag String})

下面是一个有用的metadata的key列表

:arglists doc函数调用时,参数信息

:doc doc函数调用时候,文档信息

:file 源代码

:line 代码当前行数

:macro 如果当前是宏则为真

:name local name

:ns namespace

:tag 期望的返回值或者参数类型

Metadata的read macro: ^#form 和 with-meta 还是不同的,一个是给编译器增加metadata,一个是给数据加的。

posted @ 2011-10-18 18:18  MMJX  阅读(751)  评论(0编辑  收藏  举报