本节简单引入了递归函数的定义,如下写法是合法的:
- f a c t [ n ∈ N a t ] ≜ IF n = 0 THEN 1 ELSE n ∗ f a c t [ n − 1 ] fact[n\in Nat] \triangleq\text{ IF }n=0\text{ THEN }1\text{ ELSE }n*fact[n-1] fact[n∈Nat]≜ IF n=0 THEN 1 ELSE n∗fact[n−1]
我们还需要一个工具来编写缓存内存规约,它就是递归函数定义。程序员们应该很熟悉递归函数了,经典的例子是 f a c t o r i a l factorial factorial函数,我简写成 f a c t fact fact,对所有的 n ∈ N a t n \in Nat n∈Nat, f a c t fact fact定义如下:
f a c t [ n ] = IF n = 0 THEN 1 ELSE n ∗ f a c t [ n − 1 ] fact[n] =\text{ IF }n=0\text{ THEN }1\text{ ELSE }n*fact[n-1] fact[n]= IF n=0 THEN 1 ELSE n∗fact[n−1]
按照 T L A + TLA+ TLA+的函数表示法,推荐的定义格式如下:
f a c t ≜ [ n ∈ N a t ↦ IF n = 0 THEN 1 ELSE n ∗ f a c t [ n − 1 ] ] fact \triangleq [n \in Nat \mapsto\text{ IF }n=0\text{ THEN }1\text{ ELSE }n*fact[n-1]] fact≜[n∈Nat↦ IF n=0 THEN 1 ELSE n∗fact[n−1]]
但上述定义是不合法的,因为出现在 ≜ \triangleq ≜符号右边的 f a c t fact fact未定义—— f a c t fact fact只有在定义之后才能被使用。
基于此, T L A + TLA+ TLA+允许直接循环定义递归函数,如下方式是合法的:
f a c t [ n ∈ N a t ] ≜ IF n = 0 THEN 1 ELSE n ∗ f a c t [ n − 1 ] fact[n\in Nat] \triangleq\text{ IF }n=0\text{ THEN }1\text{ ELSE }n*fact[n-1] fact[n∈Nat]≜ IF n=0 THEN 1 ELSE n∗fact[n−1]
通常,像 f [ x ∈ S ] ≜ e f[x\in S] \triangleq e f[x∈S]≜e这样的方式可以用来递归定义域为 S S S的函数 f f f。
函数定义表示法有一个直接的推广用来定义多入参的函数。例如:
A c k e r [ m , n ∈ N a t ] ≜ IF m = 0 THEN n + 1 ELSE IF n = 0 THEN A c k e r [ m − 1 , 0 ] ELSE A c k e r [ m − 1 , A c k e r [ m , n − 1 ] ] Acker[m,n\in Nat] \triangleq \\ \qquad\text{ IF }m=0\text{ THEN }n+1 \\ \qquad \qquad\text{ ELSE IF }n=0\text{ THEN }Acker[m-1,0] \\ \qquad \qquad \qquad\text{ ELSE }Acker[m-1,Acker[m,n-1]] Acker[m,n∈Nat]≜ IF m=0 THEN n+1 ELSE IF n=0 THEN Acker[m−1,0] ELSE Acker[m−1,Acker[m,n−1]]
上式对任意自然数 m , n m,n m,n,定义了一个 A c k e r [ m , n ] Acker[m,n] Acker[m,n]函数。
第 6.3 6.3 6.3节明确阐述了递归定义的含义。现在我们只需要会写递归定义即可,不必细究其深意。