多态性
使用multimethod
是一种快速在代码里面引入polymorphism
的方法,我们可以定义一个dispatching function
,然后指定一个dispatching value
,通过它来确定调用哪一个函数。
譬如,我们需要计算一个图形的面积,我们知道,如果是一个长方形,那么方法就是with * heigth
,如果是圆形,那么就是 PI * radius * radius
。
我们在repl
里面执行:
user=> (area r)
52
user=> (area c)
452.3893421169302
user=> (area {})
:oops
protocol
其实更类似其他语言里面interface
,我们定义一个protocol
,然后用不同的类型去特化实现,我们以jepsen
的代码为例,因为jepsen
可以测试很多db
,所以它定义了一个db
的protocol
。
(setup! [db test node] "Set up the database on this particular node.")
(teardown! [db test node] "Tear down the database on this particular node."))
上面的代码定义了一个DB
的protocol
,然后有两个函数接口,用来setup
和teardown
对应的db,所以我们只需要在自己的db
上面实现这两个函数就能让jepsen
调用了,伪代码如下:
然后就能直接使用DB
protocol
了。
user=> (setup! my-db :test :node)
"hello db"
user=> (teardown! my-db :test :node)
"goodbye db"
record
的定义很简单,我们使用来定义:
user=> (defrecord person [name age])
user.person
这里,我们定义了一个person
的record
,它含有name
和age
两个字段,然后我们可以通过下面的方法来具体创建一个person
:
因为record
其实可以认为是一个map
,所以很多map
的操作,我们也同样可以用于record
上面。
user=> (def siddon (->person "siddon" 30))
user=> (assoc siddon :name "tang")
#user.person{:name "tang", :age 30}
user=> (dissoc siddon :name)
{:age 30}
(defprotocol SayP
(say [this]))
(defrecord person [name age]
SayP
(str "hello " name)))
上面我们定义了SayP
这个protocol
,并且让这个record
实现了相关的函数,然后我们就可以直接使用了。