« 連載: Smalltalk use: better《6》万能メソッド★ | トップページ | 連載: Smalltalk use: better《8》基本要素の意義:リテラルとは★ »

2006年5月16日 (火)

連載: Smalltalk use: better《7》プロッククロージャー★

キーワード ◆ BlockClosure・BlockContext・value・value:・value:value:・クロージャー・クロージャー・コンテキスト・フィールド属性・ブロック引数・ブロック式・メソッド呼び出し・メソッド操作・メソッド定義

※ PDF でご覧になるなら ⇒ 「piyo60516.pdf」をダウンロード

------------ 序 ------------

グラスの底に顔があってもいいじゃないか

岡本太郎

◆ 親に連れられて大阪万博で見た「太陽の塔」は、幼心にも衝撃的でした。その当時、賛否両論が渦巻いていたのを知ったのは、大人になってからのことです。一見すると奇妙にも思えることから、拒否反応を示す人も少なからずいたようです。海外では賞賛されながら、日本ではあまり評価されないという事例には、枚挙に暇がありません。本物と偽物との違いが分るか、むしろ私たちの見識が問われるところです。

◆ オブジェクト指向についても同じかもしれません。メソッドがオブジェクトでもいいじゃないか。今日は、クロージャーについて考察します。一人前のオブジェクトであるクロージャーをメソッドと見なすなら、ブロック内で束縛される外部変数は「オブジェクトたるメソッド」の状態を示す、フィールド属性と見なせます。そして、クロージャーに送信できるメッセージ群は「オブジェクトたるメソッド」の状態変化を促す、メソッド操作と見なせます。インスタンスごとに異なる状態を持つように、クロージャーごとに異なる状態を持ちます。

◆ クロージャーのリテラル表記をメソッド定義と見なすなら、value などのメッセージを送ることはメソッド呼び出しに相当します。

------------ 本文 ------------

ブロッククロージャー ◆「すべてがオブジェクト」とするオブジェクト指向の世界では、メソッドもその例外ではありません。ブロッククロージャーは、その概念を理解するのに役立ちます。

[3 factorial] value          "6"
[3 factorial] class          "BlockContext"

60516a_2 ◆ ブロック内に記述されたメッセージ式(以下、ブロック式)が表すオブジェクトは、クラス BlockContext のインスタンスです。ブロック式はリテラルであり、オブジェクトとしての素朴な表現を提供します。また、変数に代入したり、メッセージを受け取ったりできます。よって、ブロッククロージャーは、名前を持たないメソッドと見なせます。

※ Squeak における BlockContext は、当時の Smalltalk では、BlockClosure となっています。この連載は、1988 年に作成した、Smalltalk セミナーの原稿をもとにしているので、クロージャーという表現を使っています。連載を機に、コンテキストに統一しても良かったのですが、あえて旧来の表現を使っています。その理由のひとつは、Ruby/Groovy など、他にクロージャーを使える環境と比較しやすいようにとの配慮です。

| block |
block := [3 factorial].
block value          "6"

60516b ブロック式の評価 ◆ block は、メッセージ value を受け取ると、ブロック内に記述されたメッセージ式 3 factorial を評価します。すると、その結果として 6 が得られます。

| block |
block := [:n | n factorial].
block value: 3          "6"

60516c ブロック引数 ◆ block は、メッセージ value: 3 を受け取ると、ブロック引数 n に、3 を代入します。すると、3 factorial を評価したのと同じ結果 6 が得られます。◆ ここで、ブロック引数というのは、それが出現するブロック内で有効な変数です。変数を宣言するときには「:」に続けて識別子を記述します。変数を参照するときには、単にその識別子を記述します。

| block |
block := [:a :b | a + b].
block value: 3 value: 4          "7"

60516d ◆ block は、メッセージ value: 3 value: 4 を受け取ると、ブロック引数 a および b に、それぞれ 3 および 4 を代入します。すると、3+4 を評価したのと同じ結果 7 が得られます。

| block |
block := [:op | 3 perform: op with: 4].
block value: #+          "7"

60516e ◆ block は、メッセージ value: #+ を受け取ると、ブロック引数 op に、#+ を代入します。すると、3 perform: #+ with: 4 を、つまり、3+4 を評価したのと同じ結果 7 が得られます。

| block1 block2 |
block1 := [:a :b | a + b].
block2 := [:n | n factorial].
block1 value: 3 value: (block2 value: 4)          "27"

60516f ◆ block2 は、メッセージ value: 4 を受け取ると、ブロック引数 n に、4 を代入します。すると、4 factorial を評価したのと同じ結果 24 が得られます。◆ block1 は、メッセージ value: 3 value: 24 を受け取ると、ブロック引数 a および b に、それぞれ 3 および 24 を代入します。すると、3+24 を評価したのと同じ結果 27 が得られます。

Java 擬で表現すると、次のようになります。

  block.(3)
  block.(3,4)
  block.(+)
  block1.(3,block2.(4))

==================================
真樹育未 著 ◆ 監修:小泉ひよ子とタマゴ倶楽部

|

« 連載: Smalltalk use: better《6》万能メソッド★ | トップページ | 連載: Smalltalk use: better《8》基本要素の意義:リテラルとは★ »

Squeak/Smalltalk」カテゴリの記事

.連載: Smalltalk use: better」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 連載: Smalltalk use: better《7》プロッククロージャー★:

« 連載: Smalltalk use: better《6》万能メソッド★ | トップページ | 連載: Smalltalk use: better《8》基本要素の意義:リテラルとは★ »