リスト修行(2)

Gaucheのマニュアルを見ていたら、

Gauche リファレンスマニュアル: SRFI-1 リスト構築子

circular-list elt1 elt2 ...
[SRFI-1] 指定した要素をもつ循環リストを構築します。
(circular-list 'z 'q) => (z q z q z q ...)

"循環リスト"

そ・そんなものがあったとは。試すしかねぇ。

問題

今日は日曜日。100日後は何曜日?

書いてみる

(define week (circular-list "日" "月" "火" "水" "木" "金" "土"))
(define today car)

(define (days w n)
  (if (= n 0)
      (car w)
      (days (cdr w) (- n 1))))

(today week) ; 日
(days week 100) ; 火

おぉぉぉぉぉぉぉ循環してるよ!!

(余りで計算した方が早いことは秘密)

簡単に

(define (days w n)
  (list-ref w n))

list-ref(R5RS)でlistのn番目の要素。

list-refを作ろう。

R5RSレベルを作っていこう。

(define (list-ref l n)
  (if (= n 0)
      (car l)
      (list-ref (cdr l) (- n 1))))

(list-ref '(0 1 4 9 16 25) 4) ; 16

ついでにlist-tail

list-tailは最初のn個の要素を取り除いた部分リスト

(define (list-tail l n)
  (if (= n 0)
      l
      (list-tail (cdr l) (- n 1))))

(list-tail '(0 1 4 9 16 25) 0) ; (0 1 4 9 16 25)
(list-tail '(0 1 4 9 16 25) 4) ; (16 25)
(list-tail '(0 1 4 9 16 25) 6) ; ()

list-tailで循環リストを取り出すと?

「循環リストでも構いません」と書いてあるが、どんなものが出てくるんだろう・・・右側を取り出すと・・・

疑問が湧いてきたぞ。

(list-tail week 100) ; #0=(火 水 木 金 土 日 月 . #0#)

なるほどぉ。循環リストおもろい。

おぉ

循環リストを扱う - Gaucheクックブック
素晴らしい解説。熟読しよう。