CES 341 -- Scheme チートシート

Scheme はとんでもなく単純な言語である.この言語は数種類の基本的な 概念を実現していて,それらを興味深く強力な方法で組み合わせることに よって複雑なシステムを作り上げることができる.

Read-Eval-Print ループ

これは,Schemeインタプリタの心臓部である.評価子は以下のアルゴリズム を実現している: Eval(expr: 式)

  1. exprはアトムか? それが値そのものであれは,単にそれを返す. そうでなければ,(それは名前のはずで)現在の環境からその名前 の値を取り出して返す.
  2. exprがアトムでないとき,それはリストか?最初の要素が特殊形式であれば そのルールに従う.そうでなければ(それは関数のはずなので) 最初の要素を評価して,それに残りの要素の値を【引数として】適用して 【値を返す.】

特殊形式: define, quote, lambda, cond, let/let*

;; Define は新しい名前を定義するために用いられる.名前はあらゆる値を
;; 参照することができる.(データであろうが関数であろうが関係ない.)
(define x 10)
(define double (lambda (x) (* x 2)))

;; Quote は リテラルデータ(シンボルまたはリスト)を引用("quote")する
;; ために用いられる.
(quote hello)           => hello
(quote (1 2 3))         => (1 2 3)
'(1 2 foo bar)          => (1 2 foo bar)  ; ティックマーク ' は
                                          ; 文法的な置き換え
                                          ; (シンタクティックシュガー)

;; Lambda は 新しい関数を生成するために用いられる.
(lambda (x) (+ x 10)                    ; 無名関数
(define plus10 (lambda (x) (+ x 10)))   ; その関数を名前に結びつけた.

;; Cond は一般的な条件分岐である.
(cond
  ((eq? 'foo 'bar) 'hello)
  ((= 10 20) 'goodbye)
  (#t 'sorry))                  => sorry

;; Let は一時変数を定義/利用するために用いられる
(let
  ((x 10)
   (y 20))
  (+ x y))

あらかじめ組み込まれている型と関数

Schemeでは数(整数,分数,浮動小数点数),文字,文字列,ブール値, シンボル,リストおよびベクトルをサポートしている.以下にこれらの 型について利用できるいくつかの組み込み関数の例を示す.

;; 四則演算:  +, -, *, /
;; 関係演算子: <, <=, >, >=, =
(+ 1 2)                    => 3
(= 1 2)                    => #f   ; 数には = を用いる.

;; 等価性と同一性:  eq? と equal?
(eq? 'hello 'goodbye)      => #f   ; eq? は同一性のテストである
(eq? 'hello 'hello)        => #t   ; 二つの値が全く同じものなら「eq」である
(eq? '(1 2) '(1 2))        => #f
(define foo '(1 2))
(define foo bar)
(eq? foo bar)              => #t
(equal? foo bar)           => #t   ; 同じに見える2つの値は「equal」である
(equal? foo '(1 2))        => #t

;; リスト:  cons, car, and cdr
;; quote, cons, またはlist で新しいリストを作る
(define foo '(1 2 3))
(define bar (cons 1 (cons 2 (cons 3 ()))))
(define baz (list 1 2 3))

;; car, cdr, and null? を用いてリストを操作する
(null? '(1 2))             => #f
(null? ())                 => #t
(car '(1 2))               => 1
(cdr '(1 2))               => (2)

再帰を用いた繰り返し

;; 指数関数 x^n
(define expt
  (lambda (x n)
    (cond ((= n 0) 1)
          (#t (* x (expt x (- n 1)))))))

;; リストの長さ
(define length
  (lambda (a-list)
    (cond ((null? a-list) 0)
          (#t (+ 1 (length (cdr a-list)))))))

高階関数

Schemeでは関数は第1級のデータである.すなわち,引数として他の関数に 渡したりすることができる.

;; 2つの関数【f, g 】と1つの引数【x】をもらって を計算して (f (g x)) を返す
(define compose
  (lambda (f g x)
      (f (g x))))

(compose even? (lambda (x) (- x 1)) 10)   => #f

;; ある関数をもらってあるリストのすべての要素に適用する
(define map
  (lambda (f a-list)
    (cond ((null? a-list) a-list)
          (#t (cons (f (car a-list)) (map f (cdr a-list)))))))

(map even? '(1 2 3 4))        => (#f #t #f #t)