相互遞歸(1)

  版權申明:本文爲博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須註明原文網址

  http://www.cnblogs.com/Colin-Cai/p/10787636.html 

  做者:窗戶

  QQ/微信:6679072

  E-mail:6679072@qq.com

  相互遞歸就是多個函數互相定義,最多見的就是兩個函數,好比f和g,f的定義中用到g,而g的定義中用到f。html

  相互遞歸同樣有無限遞歸的可能,最簡單的:sql

  f:x->g(x)微信

  g:x->f(x)閉包

  

  給個最簡單的沒有無限遞歸的例子,判斷一個正整數是否是偶數或者是否是奇數,用C++來描述以下:app

bool is_odd(unsigned x);
bool is_even(unsigned x)
{
        if(x == 0u)
                return true;
        return is_odd(x-1u);
}
bool is_odd(unsigned x)
{
        if(x == 0u)
                return false;
        return is_even(x-1u);
}

 

  以上效率雖然不高(甚至不優化的狀況下,可能會崩棧),可是is_even和is_odd兩個函數畢竟是相互定義的,也是相互遞歸的一個經典例子。函數

  

  Scheme固然同樣支持相互遞歸,r5rs中也是以上述奇偶來作例子。學習

(define (even? x)
 (if (zero? x)
  #t
  (odd? (- x 1))
 )
)
(define (odd? x)
 (if (zero? x)
  #f
  (even? (- x 1))
 )
)

 

  再給個稍微複雜的例子,Scheme裏的append是個經常使用的函數,它能夠傳入一組列表,獲得這組列表首尾拼接在一塊兒的列表。好比:(append '(1 2 3) '(4 5 6) '(7 8 9))獲得(1 2 3 4 5 6 7 8 9)。測試

  每一個人學習Scheme的過程,基本必然伴隨着append函數的自我實現。優化

  如下是其中一種實現(固然,append有好幾種不一樣的實現思想):spa

(define (append . lst)
 (if (null? lst)
  '()
  ((apply _append (cdr lst)) (car lst))
 )
)

(define (_append . lst)
 (cond
  ((null? lst) (lambda (x) x))
  ((null? (cdr lst))
   (lambda (x)
    (if (null? x)
     (car lst)
     (cons (car x) ((_append (car lst)) (cdr x)))
    )
   )
  )
  (else (_append (apply append lst)))
 )
)

 

 

  固然,_append通常應該實如今append的內部,我這麼寫也是爲了表示的清楚一點。這種寫法是一種相對高級一點的寫法,採用的算子方式,不斷用閉包來傳遞信息,並使用了相互遞歸,append和_append兩個函數互相定義。

 

  固然,一開始就說了,相互遞歸徹底能夠不僅是兩個函數之間的關係,能夠是多個函數之間的關係。

  我這裏給個例子,把正整數按照除以3獲得的餘數分爲三類,把整除3的數稱爲type0,把除以3餘1的數稱爲type1,把除以3餘2的數稱爲type2。因而定義三個謂詞函數type0? type1? type2?

  如下爲實現:

(define (type0? x)
 (if (= x 0)
  #t
  (type2? (- x 1))
 )
)
(define (type1? x)
 (if (= x 0)
  #f
  (type0? (- x 1))
 )
)
(define (type2? x)
 (if (= x 0)
  #f
  (type1? (- x 1))
 )
)

 

  咱們能夠看到,

  type0?的定義中用到type2?

  type1?的定義中用到type0?

  type2?的定義中用到type1?

 

  測試一下,

(for-each
 (lambda (x) (display x)(newline))
 (map
  (lambda (x)
   (cons
    x
    (map (lambda (f) (f x)) (list type0? type1? type2?))
   )
  )
  (range 20)
 )
)

  

  獲得

  

(0 #t #f #f)
(1 #f #t #f)
(2 #f #f #t)
(3 #t #f #f)
(4 #f #t #f)
(5 #f #f #t)
(6 #t #f #f)
(7 #f #t #f)
(8 #f #f #t)
(9 #t #f #f)
(10 #f #t #f)
(11 #f #f #t)
(12 #t #f #f)
(13 #f #t #f)
(14 #f #f #t)
(15 #t #f #f)
(16 #f #t #f)
(17 #f #f #t)
(18 #t #f #f)
(19 #f #t #f)

相關文章
相關標籤/搜索