2つのデータをまとめたもの.通常は後述するリストを使用することが好まれる.
コンスに対する基本操作を以下にまとめる:
以下を Definitions に記述し,Run してみよう.
(define p1 (cons 100 200)) (car p1) (cdr p1) |
コンスを組み合わせて,データを並べたものがリストである.
リストに対する基本操作を以下にまとめる:
リストの個々のデータを扱う関数を作ってみよう.
実行方法: (sum-list (list 1 2 3 4 5))
(define sum-list (lambda (lst) (if (null? lst) 0 (+ (car lst) (sum-list (cdr lst)))))) |
実行方法: (print-list (list 1 2 3 4 5))
(define print-list (lambda (lst) (if (not (null? lst)) ((lambda () ここの lambda は (write '<) これら write と print-list の順接を (write (car lst)) 実行するために (write '>) 使われている. (print-list (cdr lst))))))) lambda の前に括弧が2つあることに注意 |
実行方法: (max-list (list 1 2 4 5 3))
(define max-list (lambda (lst) (if (= 1 (length lst)) もし長さが1のリストならば, (car lst) リストの先頭の数値が最大値 ((lambda (m n) そうでなければ,2つの数値 m と n について (if (> m n) m n)) 大きい数値を返す関数に, (car lst) リストの先頭の数値と (max-list (cdr lst)))))) リストの2番目以降の最大値を比較してもらう. |
上記の max-list の意味がわからない人は以下の定義をまず考えてみよう.
(define max-list01 (lambda (m n) (if (> m n) m n))) (define max-list (lambda (lst) (if (= 1 (length lst)) (car lst) (max-list01 (car lst) (max-list (cdr lst)))))) |
以下の定義でも動作するが,無駄が多い? 関数型言語ならば,引数が同じ関数呼出しは同じ答えが得られるはずであり,無駄な計算はないので,無駄にはならない?
(define max-list (lambda (lst) (if (= 1 (length lst)) (car lst) (if (> (car lst) (max-list (cdr lst))) (car lst) (max-list (cdr lst)))))) |
上記の例は,リストから値を抽出する関数であった.次にリストを加工してみよう.
実行方法: (my-append (list 1 2 3) (list 4 5 6))
(define my-append (lambda (lst1 lst2) (if (null? lst1) lst2 (cons (car lst1) (my-append (cdr lst1) lst2))))) |
実行方法: (double (list 1 2 3 4 5))
(define double (lambda (lst) (if (null? lst) (list ) (cons (* 2 (car lst)) (double (cdr lst)))))) |
実行方法: (add-next (list 1 2 1))
(define add-next (lambda (lst) (if (< (length lst) 2) (list ) (cons (+ (car lst) (car (cdr lst))) (add-next (cdr lst)))))) |
よく使うプリンタの用紙は,A4サイズである(210mm x 297mm).この用 紙は,長辺を半分に折るとA5サイズの用紙になる(小数点は切り捨て. truncate関数).A0サイズは,841mm x 1189mm という大きさである.では, nを変数として Anサイズの2辺の長さをペアの値で返す関数 (paper-a-size n) を定義せよ.
ヒント:ペアのデータ1を短辺,データ2を長辺とすることにする.
ヒント:ペアのデータを入力として,長辺を折り曲げて新しい短辺とし,短辺を新しい長辺としてペアの値を返す関数を作ってみる.
問題を説明する前に,次の式を見てみよう.
右辺の係数に注目すると,次の図のような関係が見えてくる.この図をパスカルの三角形という.
(a+b)の羃乗の数ごとに,係数をリストで表すと,次のようになる.
(a+b)nのときの係数のリストを返す関数 pascal-list を定義せよ.
ヒント:pascal-list では,n = 1 のとき,「(list 1 1)を返すこと」として,そのほかのとき,「先頭が 1 であり,そして,残りが n - 1 の pascal-list の返り値について add-next のような計算をしたもの」とするとよい.つまり,(1 3 3 1)を求める計算では,(1 2 1)から(3 3)を求めて,前後に (1) を append すると実現できる.
できた人は,append を使わずに,cons を使って関数 pascal-list を定義しよう.