第6回 Scheme 入門(5月14日;5月22日)

今日の課題

■ 関数型言語 scheme

scheme は関数型言語 lisp の方言の一つである。

関数型言語の基本:

<式>を<評価> して、<返り値>を得る

■ DrScheme の環境と操作

処理系

知能情報工学科の計算機には、DrScheme がインストールされている。 DrScheme は、Scheme のプログラミング環境の一種である。 ここがホームページである:http://www.plt-scheme.org/ Windows用もある。

準備

演習のために準備しよう。コンソール上で以下を実行しよう。
mkdir -p ~/2009-Lect-3/Scheme/     (ディレクトリの作成)
cd ~/2009-Lect-3/Scheme            (演習場所に移動)
drscheme                           (Scheme の起動)

主な操作方法

以下に主な操作方法を示す。
起動方法 コンソール上で drscheme を実行する
ウインドウ デフォルトでは、メニュー行、ツールバー、および、2つの白いエリアがある
上のエリア:式を定義するエリア(Definitions)
下のエリア:対話的に式を評価(実行)するエリア(Interactions)
マニュアル メニューの中の「ヘルプ」の中の「ヘルプデスク」より検索が可能
プログラムの作成 定義エリアに書き込む
プログラムの実行 実行(Run)ボタンを押した後、対話エリアで、式を入力する(たとえば、関数に具体的な値を与える)
プログラムの保存 メニューの中の「ファイル」の中の「定義の保存」を選択する※
プログラムの読み込み メニューの中の「ファイル」の中の「開く」を選択する
終了方法 メニューの中の「ファイル」の中の「Quit」を選択する

※ この選択で定義エリアのみを保存する。対話エリアの保存は、「その他の保存」より行う。

■ 式(フォーム)

式には次の種類がある:

■ 評価

評価の方法:

□ 「定数」の評価

主な定数を以下に示す。

※ シンボルと文字列は、実体が共通か否かという点で異なる。

練習1

以下の定数である式を評価しよう。対話エリアに入力し、Enterキーを押して、返り値を確認しよう。
> 100      ⇒ 100 が返り値となる。
> 3/4      ⇒ 分数を評価すると,3/4が返り値となる。
                 言語(ツールバー)の選択によっては実数で返り値が表示される。
> 'hello   ⇒ シンボルとしての hello が返り値となる。

実は、演算子や関数名も評価できる。対話エリアで返り値を確認しよう。
> +        ⇒ 足し算の本体である #<procedure:+> が返り値となる。
> sin      ⇒ 正弦関数の本体である #<procedure:sin> が返り値となる。

□ 「コンビネーション」の評価

コンビネーションは、以下の形式となっている。
(〈式1〉  〈式2〉 〈式3〉 〈式4〉… 〈式n〉)

〈式1〉のことを、最左部分式と呼ぶ。コンビネーションの評価とは、〈式1〉から〈式n〉までを個別に評価した後、最左部分式の評価結果(式1の返り値)に、残りの部分式の評価結果を渡して評価する。このとき、最左部分式の評価結果は #<procedure> でなければならない。

練習2

対話エリア 上で、「コンビネーション」の式を評価してみよう。
> (- 5)                         ⇒ 単項演算
> (+ 1 2)                       ⇒ 2項演算
> (sqrt 2)                      ⇒ 組み込み関数。√2 のこと
> (+ (* 2 3) 4)                 ⇒ 中置記法では「 2 * 3 + 4」
> (* (+ 1 2) (- 3 (/ 4 5)))     ⇒ 中置記法では「(1 + 2) * (3 - 4 / 5)」
> (sin (/ 3.141592653589793 2)) ⇒ 引数部に式を与えている。数学の記法では、sin(π/2) のこと

□「特殊形式」の評価

特殊形式は、記述形式は、コンビネーションと同様であるが、最左部分式が特定の語である。たとえば、次のものがある。

練習3

対話エリア上で、「特殊形式」の式を評価してみよう。
> (define x 100)           ⇒ 100 に x という名前を付ける。
> (set! x 200)             ⇒ x の指す対象を 200 とする(詳細は後の回で演習します)。
> (if (= x 100) 'ok 'ng)   ⇒ 〈式2〉の評価結果が #f でなければ〈式3〉を評価し、#f ならば〈式4〉を評価する(詳細は後の回で演習します)。
> (lambda (x) (* x 3))     ⇒ 引数 x をとり、x * 3 を返す関数を表す(詳細は後の回で演習します)。

□「変数」の評価

define で作成した名前は、評価をすると、指している対象を返す。

練習4

対話エリア 上で、「変数」の作成とその評価をしてみよう。
> (define x 100)       ⇒ 特殊形式の評価。「100」の評価結果に「x」という名前を付けた。
> x                    ⇒ 変数の評価。変数 x を評価すると、対応する式が返り値となる。
> (define san (+ 1 2)) ⇒ 特殊形式の評価。「(+ 1 2)」の評価結果に san という名前を付けた。
                             つまり、「3」に「san」という名前を付けた。
> san                  ⇒ 変数の評価。変数 san を評価すると、対応する式(定数 3)が返り値となる。
> (define tasu +)      ⇒ 特殊形式の評価。「+」の評価結果(#<procedure:+>)に、tasu という名前を付けた。
> (tasu 1 2)           ⇒ 「コンビネーション」の評価。
> tasu                 ⇒ 変数の評価。
> (tasu x san)         ⇒ 全体はコンビネーションの評価。〈式1〉から〈式3〉までをそれぞれ評価して、
                             〈式2〉と〈式3〉の評価結果を〈式1〉の評価結果に渡して評価してもらう。
			     つまり、100 と 3 を #<procedure:+> に評価してもらう。

■ ドリル

練習5

果物の名前と価格を定義し、その名前を使って、果物の代金を計算しよう。

価格は次のように設定しよう。

apple 110
orange 90
pineapple 230
peach 190

例として、apple 3つ、orange 5つ、pineapple 1つ、peach 5つの代金の合計を計算しよう。


  1. 定義エリアで入力
    (define apple 110)
    (define orange 90)
    (define pineapple 230)
    (define peach 190)
    
  2. 実行(Run)ボタンを押す
  3. 対話エリアで評価
    > (+ (* apple 3) (* orange 5) (* pineapple 1) (* peach 5))
    

上記の定数の定義をファイル「prac0605.scm」に保存しよう。また、いったんdrscheme を終了し、再び起動して、定義ファイルを開いてみよう。

練習6

練習5の続きとする。贈り物用のフルーツセット(giftbox)には、melonが1つ、appleが5つ、orangeが3つ入っている。ここで、melon は単価が 800 円とする。giftbox の代金は、入っている果物の代金と箱代(box)50円の合計とする。giftbox の代金を定義しよう。

お得用フルーツセット(specialbox)には、1割引の桃が3つ、定価のパイナップルが1つ、2割引のオレンジが5つ入っている。箱代を30円とする。specialbox の代金はそれらの果物の代金と箱代の合計とする。specialbox の代金を定義しよう。

以上の定義を prac0606.scm に保存しよう。

  1. 対話エリアで、giftbox を評価せよ。
  2. 対話エリアで、specialbox を評価せよ。
  3. 対話エリアで、giftbox 2セットと specialbox 3セットの代金の合計を計算せよ。

練習7

tan の逆関数は atan である。tan(π/4)は1になるので、atan(1)はπ/4となる。そこで、atan を利用して、円周率 3.141592.... に pi と名前を付けてみよう。


(c) 2009.5.11 by tokuhisa