第5回 継続を使ったコントローラを作る

吉田 裕美
有限会社イーワイオフィス

2009/2/20

Lispの一種であるScheme。いくつかある処理系の中でも気軽にスクリプトを書けるGaucheでLispの世界を体験してみよう(編集部)
- PR -

 第4回「Gaucheでテンプレートエンジンを作る」では、MVCのビューの部分を作成しました。今回は、継続を使ったコントローラ部分の作成を行い、Webアプリケーションを完成させます。

 Webアプリケーションのコントローラの解説に入る前に、プログラムの処理の流れについて少し考えてみます。

 例えば、2つの数を入力して足した結果を表示するコンソールアプリケーションであれば、以下のように変数を2つ用意し、2つの数値を入力した後で足した結果を表示するというシンプルなプログラムになります。

(define (console-add)
  (let ((a 0) (b 0))
    (display "Aを入力して下さい: ") (flush)
    (set! a (read))
    (display "Bを入力して下さい: ") (flush)
    (set! b (read))
    (display "A + B は ")
    (print (+ a b))))

 しかし、皆さんが書いているようなWebアプリケーションではどうでしょうか。1つのページにAとB、2つの入力欄があれば簡単ですが、1ページ目でAを入力し、2ページ目でBを入力し、3ページ目に表示するようなアプリケーションの場合は、1ページで入力したAの値を2ページ目の入力の間も保持するために、セッションなどの特別な場所に格納するか、2ページ目にhiddenタグを使って埋め込んでおく必要があります。

 これは、リクエストごとに起動されるCGIはもちろんですが、アプリケーションサーバ上に常駐して動くアプリケーションの場合も同じです。なぜ、上のコンソールアプリケーションのようにシンプルに書けないのでしょうか。

クロージャ

 ここでまた、Schemeの勉強をしましょう。次のようなadd-nという関数を定義します。

(define (add-n n)
  (lambda(x) (+ x n)))

 この関数を使ってadd3を定義します。

(define add3 (add-n 3))

 add3を実行してみましょう。

gosh> (add3 5)
8

 add3は引数に3を足す関数になっています。同じようにadd4を定義して使ってみると、add4は引数に4を足す関数になっています。

gosh> (define add4 (add-n 4))
add4
gosh> (add4 5)
9

 ところで、最初に定義したadd-nは何でしょうか。定義を見ると、lambda式を戻す関数です。しかも、引数nが足し算の片方に使われています。

 従って、add3は(lambda(x) (+ x 3))となり、引数xを受け取り、3を足します。しかも、add3の定義で使った3が、ずっとその後でもどこかに記憶されていて、いつでも3を足す関数として使えます。

 このような機構は、クロージャ(Closure)と呼ばれています。Schemeでは、lambda式は実行するプログラム(上の例では(+ x n))だけではなく、定義した際の環境(ここではnの値)も一緒になっているのです。

 従って、add3には(lambda(x) (+ x n))とn = 3の環境が一体化して記憶されているのです。

継続ベースのアプリケーション

 さて、ここで最初のA+Bのプログラムに戻りますが、クロージャを使って以下のように書き換えてみました。

(define cont #f)

(define (continuation-add)
  (let ((a 0) (b 0))
    (cond (cont (cont) (set! cont #f))
    (else
     (display "Aを入力して下さい: ") (flush)
     (set! a (read))
     (set! cont
           (lambda()
             (display "Bを入力して下さい: ") (flush)
             (set! b (read))
             (display "A + B は ")
             (print (+ a b))))))))

 これを実行すると、

gosh> (continuation-add)
Aを入力して下さい: 2
#<closure (continuation-add continuation-add)>
gosh> (continuation-add)
Bを入力して下さい: 3
A + B は 5

となります。このプログラムは、Aを入力したところで終了してしまいますが、再度実行するとBの入力と計算結果の表示が行われます。Webアプリケーションに似ていると思いませんか。

 プログラムを説明すると、contという広域変数に値がある場合はそれを関数として実行し、cont変数をfalseに戻します。contがfalseの場合は、Aを入力し、B入力以降の処理をクロージャとしてcont変数に代入しています。

 ここで特筆すべきことは、aの値は明示的に保存してないにもかかわらず保存されていて、2回目の実行で使えることです。また、(set! cont (lambda()などの余分なコードが入っていますが、処理の大部分は最初に説明したシンプルなプログラムそのままです。

 このようなスタイルのプログラムは、継続ベースのアプリケーションと呼ばれています。schemeの継続という言葉は、厳密にはここに書いたものとは異なる側面もありますが、ここではこれ以上は追求しないことにします。

 このプログラムでは、継続すべき処理を1つの広域変数にしまっているので現実的なWebアプリケーションには使えません。そこで、次項ではもう少し実用に近い継続ベースのWebアプリケーションを作ってみます。

 
1/3

Index
継続を使ったコントローラを作る
Page1
クロージャ
継続ベースのアプリケーション
  Page2
継続ベースのWebアプリケーションを作る
モジュール
templateモジュール
serverプログラム
  Page3
controllerモジュール
ORMモジュール
userモジュール
テンプレート
まとめ

Gaucheでメタプログラミング

 Coding Edgeお勧め記事
いまさらアルゴリズムを学ぶ意味
コーディングに役立つ! アルゴリズムの基本(1)
 コンピュータに「3の倍数と3の付く数字」を判断させるにはどうしたらいいか。発想力を鍛えよう
Zope 3の魅力に迫る
Zope 3とは何ぞや?(1)
 Pythonで書かれたWebアプリケーションフレームワーク「Zope 3」。ほかのソフトウェアとは一体何が違っているのか?
貧弱環境プログラミングのススメ
柴田 淳のコーディング天国
 高性能なIT機器に囲まれた環境でコンピュータの動作原理に触れることは可能だろうか。貧弱なPC上にビットマップの直線をどうやって引く?
Haskellプログラミングの楽しみ方
のんびりHaskell(1)
 関数型言語に分類されるHaskell。C言語などの手続き型言語とまったく異なるプログラミングの世界に踏み出してみよう
ちょっと変わったLisp入門
Gaucheでメタプログラミング(1)
 Lispの一種であるScheme。いくつかある処理系の中でも気軽にスクリプトを書けるGaucheでLispの世界を体験してみよう
  Coding Edgeフォーラムフィード  2.01.00.91

TechTargetジャパン

Coding Edge フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH