Programming Clojure学习笔记——探索Clojure

本文深入探讨了Clojure中元数据的应用,包括如何通过with-meta和meta宏添加元数据,以及如何利用元数据进行对象属性的继承和类型注解。同时,介绍了元数据在变量和函数定义中的使用方式,以及如何通过元数据进行参数验证和类型检查。
2.6  元数据
在Clojure中,元数据(metadata) 是与对象逻辑值正交的数据。
如person的firstname 和 lastname是普通旧数据。而person对象可以被序列化到XML文件的信息就是元数据。同样person对象被更改需要保存到数据库的信息也是元数据。

可以使用with-meta给集合(collection)和符号(symbol)添加元数据:
(with-meta object metadata)
如:
(def stu {:name "Stu" :email "stu@thinkrelevance.com"})
(def serializable-stu (with-meta stu {:serializable true}))
说明:
(with-meta stu {:serializable true})给stu添加元数据,说明stu可序列化
metadata不会对改变原对象依赖对象值的操作结果,即添加元数据前和后的对象是相等的:
user=> (= stu serializable-stu)
true
=判断值是否相等,类似Java的equals。如果要判断是否同一个对象,需要使用identical?谓语:
(identical? obj1 obj2)
identical?类似Java的==,可以用identical?判断stu和serializable-stu是不同的对象:
user=> (identical? stu serializable-stu)
false

可以使用meta宏访问元数据,如:
user=> (meta stu)
nil
user=> (meta serializable-stu)
{:serializable true}

meta宏对应的读者宏为^:
user=> ^stu
nil
user=> ^serializable-stu
{:serializable true}

元数据可以被继承,在已有对象的基础上创建新对象,则新对象拥有已有对象的元数据。
user=> (def stu-with-address (assoc serializable-stu :state "NC"))
#'user/stu-with-address
user=> ^stu-with-address
{:serializable true}
说明:assoc函数给map添加key/value对象,然后返回新map

读者元数据
给变量var添加key/value对,使用元数据读者宏:
#^metadata form
创建shout函数,将字符串变大写,然后使用:tag关键字说明只能接受字符串参数并返回字符串值:
user=> (defn #^{:tag String} shout [#^{:tag String} s] (.toUpperCase s))
#'user/shout
如果试图传入非字符串参数,则抛出异常:
user=> (shout 1)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String (NO_SOURCE_FILE:0)

:tag元数据有一个简写形式:
#^Classname 等同 #^{:tag Classname}
shout函数可以重写为:
user=> (defn #^String shout [#^String s] (.toUpperCase s))
#'user/shout

为了便于阅读函数定义,还可以将元数据放到函数定义最后:
user=> (defn shout
              ([s] (.toUpperCase s))
              {:tag String})
#'user/shout

常见元数据key如下表所示:
MetadataKey      Used For
:arglists Parameter info used by doc
:doc Documentation used by doc
:file Source file
:line Source line number
:macro True for macros
:name Local name
:ns Namespace
:tag Expected argument or return type

说明:元数据读者宏与with-meta不同,元数据读者宏给编译器添加元数据,而with-meta给自定义的数据添加元数据。
user=> (def #^{:testdata true} foo (with-meta [1 2 3] {:order :ascending}))
#'user/foo
user=> (meta #'foo)
{:ns #, :name foo, :file "NO_SOURCE_PATH", :line 29, :testdata true}
user=> (meta foo)
{:order :ascending}
说明:一般来说,给变量和参数添加元数据使用元数据读者宏,给数据添加元数据使用with-meta。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值