Gaucheプログラミング(立読み版) > 第1部: 思想 > すべて式である


[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

すべて式である 応援する 

Scheme では計算というのは式の値を求めることです。

Scheme の式は以下のように表現されているものです。

  1. ひとつ塊(シンボルおよびリテラル)として表現されるもの(この構文のこと をアトムということがあります)
  2. 複数の式を括弧(())で囲って表現されるもの(この構文のこ とをリストということがあります)
  • 1. により、mapstring=?*-53.14"The Wizard Book"#\a などはどれも式です。
  • 2. により、(- 1 (* 2 3))(string->list (string-map char-upcase "wikiwiki")) なども式です。

式が表す値に名前をつけることを定義といいます。Schemeでは式が表す値に 名前を付けることによって、複雑な構成の式をひとつのものとして抽象化して 表現することができます。

計算機に計算をさせるには、対話型のインタプリタを使うのが簡単です。 式が表す値はその式を評価(eval)すること、すなち計算することによって 得られます。式が表す値を確認するために対話型のインタプリタを起動して計 算をさせてみましょう。

コマンドラインでgoshとタイプするとインタプリタが起動します。

 $ gosh
 > _

起動するとインタプリタは> という入力促進記号(プロンプト)を出力して、 ユーザからの入力待ち状態になります。ここで式をタイプして最後にリターン キーを押すとインタプリタはユーザがタイプした式を読み(read)、 それを評価(eval)し、結果を印字(print)し、再びプロンプトを出し て入力待ち状態になります。

 gosh> 1
 1
 gosh> _

他にも試してみましょう。

 gosh> "hello"
 "hello"
 gosh> (+ 1 3)
 4
 gosh> (let1 abs (lambda (n)
                      (if (<= 0 n)
                          n
                          (- n)))
            (abs -1))
 1

すべて式とはどういうことか

たとえば、Scheme では if は式なので値を返します

a に「bの絶対値」を加算するプログラムを考えて見ましょう。 絶対値を求める手続き abs を使わないとすると、

 (define (a-plus-abs-b a b)
   (if (>= b 0)
        (+ a b)
        (- a b))) 

と書けます。これは if 式全体の値が手続き適用したときの値として返されま す。また、if 式は値を返すので、その値そのものとみなすことができるので、

 (define (a-plus-abs-b a b)
   (+ a (if (>= b 0)
            b
            (- b)) ))

のように b の値の正負によって,b か -b を返すように書いています。 さらに Scheme では手続きそのものも値ですので、手続きを値として返す 式を書けます。以下の定義で if 式は b が正の値なら + 手続きを、 負の値なら - 手続きを返しています。

 (define (a-plus-abs-b a b)
   ((if (> b 0)
          +
          -) a b))

例えば a が 23、b が 16 ならば、

((if (> 16 0) + -) 23 16)
↓
(+ 23 16)
↓
39

aが12、bが-74ならば、

((if (> -74 0) + -) 12 -74)
↓
(- 12 -74)
↓
86

と計算できます。


代入がなくても計算はできる

Schemeにおいて計算する対象はすべて式であるなら、代入文はないということ になります。代入文がなくてプログラムが書けるのでしょうか。

書けます。

1 から指定した上限 n までの整数の和をもとめる計算を考えてみましょう。

 1 + 2 + ... + (n-1) + n

このプログラムを書くのに代入文が欲しいですか。 こんな風に計算させようとしていますか。

  1. s に 0 を代入
  2. i に 1 を代入
  3. i が n を超えない間 4 〜 5 を実行、n を超えたら 6 へ
  4. s + i を計算してその結果を s に代入
  5. i + 1 を計算してその結果を i に代入
  6. s の値を印字

なるほど。これで計算できるような気がします。でもこれで本当に欲しい ものが手にはいるかどうかは、よくよく読んで検討しないと分りませんね。

こんな風に欲しいものを「どのように」得るかの手順を考えるのではなくてもっと、 単純に考えることもできます。これを行う関数を sum としましょう。 こんな風に考えます。

  1. n が 1 のとき、(sum n) の値は 1
  2. n が 1 より大きいとき、(sum n) の値は、ひとつ手前 (n-1) までの和 (すなわち (sum (- n 1))) と n との和

これを書くと、

  (define (sum n)
    (if (= n 1)
        1
        (+ (sum (- n 1)) n)))

欲しいものが「何か」を書いただけです。でも欲しいものはちゃんと書けてい るということは分りますよね。どこにも代入は必要ありませんでしたね。

ではなぜ、最初は代入が必要だと思ったのでしょう。 「プログラムは計算の手順を書いたもの」という先入観がどこかに ありませんでしたか。


[Prev] [Next] [Up] [Contents][フレーム表示] [フレーム解除

このサイトについて|ヘルプ|Q&A|個人情報保護|プライバシーポリシー|利用規約|コメント・トラックバック規約|削除規程|広告掲載
Copyright (c) 2005-2007 Time Intermedia Corporation