今回は構文の概略をします。
構文全体をお見せしますが
完全に理解できなくても 深刻にならないでください。
後でまた繰り返しますので。
まずは Pharo にある構文全てをお見せします。
まずは主要な構文要素を見ていきましょう。
3 種類のメッセージを見て
そしてブロック構文を見ます。
Pharo の本質的な部分です。
全てを理解できなくても心配しないでください。 全てまたやりますので。
思い出してください。 全ての構文がこのスライドに載っています。
これからちょっとだけ詳細に踏み込みます。
これは exampleWithNumber のメソッド定義です。
引数があります。
縦棒がついたローカル変数定義があります。
値を返す、リターンがあります。
ループがあり、代入があります。
ピリオドは、命令のセパレーターです。
これらを全て見ていきます。
伝統的といえる Hello World から始めます。
ここで、もし良かったら
全ての命令は Pharo 上で実行して
結果を見ることができます。
ここに文字列がありますが
グラフィック要素である Morph に変換して
ウィンドウで開くように お願いすることができます。
つまり、文字列オブジェクトに asMorph を送り
openInWindow を
得られた Morph に送ります。
つまり、2 つのメッセージ送信と 1 つの文字列オブジェクトがあります。
より複雑な例もあります。
ウェブから Pharo のロゴを 取得したいとします。
その方法はこうです。
ZnEasy getPng: を URL 文字列 を付けて実行します。
読み込みたいリソースの URL です。
そして、またグラフィックオブジェクトに変換し
ウィンドウで開くようにお願いします。
ZnEasy はクラスです。
クラスは大文字で始まります。
getPng: メッセージのコロン（:）は 引数がくるという意味です。
引数は文字列 http://pharo.org です。
この文字列は getPng: メッセージの引数です。
asMorph メッセージと openInWindow メッセージは
左から右へと読みます。
ここで、このコードを Pharo 上に
コピー＆ペーストするかキーボード入力すれば
Pharo のロゴが得られます。
Pharo にはどんな構文要素があるのでしょう？
コメントがあります。 二重引用符で始まります。
これがコメントです。
文字は頭にドルマークが付きます。
$A は文字 A です。
文字列は引用符で始まり 引用符で終わります。
シンボルがあります。 ユニークな文字列です。
シンボルはこんな風に ハッシュタグが付いています。
#a はシンボル a です。
リテラル配列があります。
これは 12、23、36 の 3 要素からなる リテラル配列です。
整数には様々な表現がありますが
それについては掘り下げません。
通常は 10 進法表現を使います。
しかし必要ならば 2 進法も使えます。
実数もあります。 同じように色々な表現があります。
必要ならば構文を見つけることができます。
true と false の真偽値があります。
未定義値もあります。
Java での null は Pharo では nil です。
nil は UndefinedObject クラスの インスタンスです。
点もあります。
Pharo での点は
例えば 10 @ 200 と表現します。
x が 10、y が 200 の
点を生成します。
構文の本質的な要素を見てきました。
言語の構成を見ていきます。
一時変数宣言があります。
一時変数宣言は縦棒のペアです。
代入はコロンと等号です。
変数 var に aValue を代入します。
メッセージがあります。
一連のメッセージを
区切るのは
ピリオドです。
リターンがあります。
関数やメソッドが値を返します。 gives a value.
英語でいうところのキャレットを使います。
そしてブロックがあります。
技術的に言えばレキシカルクロージャですが are lexical closures,
匿名メソッドと見做してもかまいません。
ブロックについて簡単に説明します。
ブロックは角括弧で定義されます。
ブロックは value メッセージで実行されます。
あとで見てみましょう。
これで全ての構文構成です。
それでは Pharo プログラムの本質は何でしょう？
それは、メッセージを使って オブジェクトを作ることです。
これらのオブジェクトにメッセージを送って
あれやこれや、ブロックを使って。
それが全てです。
Pharo には 3 種類のメッセージがあります。 なぜでしょう？
必要な括弧の数を最小限にするためです。
メッセージは良い感じにシンプルです。
単項メッセージはレシーバーとセレクター から成っています。
例えば、9 squared （9 の自乗）です。
今日の日付が必要であれば
Date クラスに today メッセージを送ります。
引数はありません。
次に、二項メッセージです。
二項メッセージは レシーバー、セレクター、引数、という形式です。
ただし、セレクターは
+, -, ~, =, 等です。
これらの数学的な記号は全て二項メッセージです。
ここに 1 + 2 とありますが これはメッセージです。
オブジェクト 1 に メッセージ + を 引数 2 を付けて送ります。
@ で点を生成するのもメッセージです。
二項メッセージです。
ここで、点 3 @ 4 を
メッセージ @ を送ることで 生成しています。
そして、我々が呼ぶところの キーワードメッセージがあります。
キーワードメッセージは
レシーバー、キー1:、引数1、キー2:、引数2 という形式を取ります。
例えば…
2 between: 10 and: 20 です。
これを Java や C で書くとしたら
betweenAnd(10, 20)
のように書くでしょう。
Pharo ではこれを キーとキーという形式で表現します。
後でまた見ますが、これが構文のポイントです。
メッセージ間に優先順位があります。
システムは次の優先順位で実行します。 括弧
単項メッセージ 二項メッセージ、そしてキーワードメッセージ。
こうなっているのは
煩雑な括弧を書かずに済ませるためです。
やろうと思えば、あらゆるところで 括弧だらけにしても良いのですが
コードはまともに読めなくなるでしょう。
それぞれの種類のメッセージについて 簡単におさらいします。
単項メッセージ。 10000 factorial
実行してみてください。 とても大きな数です。
オブジェクト 10000 に メッセージ factorial を送ります。
引数はありません。 それが単項メッセージです。
同様に、二項メッセージがあります。 1+3 は二項メッセージです。
セレクター つまりメソッドの名前は、+ です。
オブジェクト 1 に メッセージ + を 引数としてオブジェクト 3 を付けて送ります。
キーワードメッセージは 前に説明しましたが
また説明します。 教えるということは繰り返すということです。
キーワードメッセージは
引数付きのメッセージで
引数はメッセージの中に入り込んでいます。
元の発想としては 子供がつかうための構文で
ある意味、英語に近いものです。
引数をメッセージの内側に取り込みます。
例えば、HTTP リクエストを送るとします。
ZnClient は Pharo の HTTP クライアントです。
Zn クライアントのインスタンスを生成します。
new は単項メッセージで 引数はありません。コロンはありません。
url: はキーワードメッセージで コロンが付いています。
queryAt:put:
もキーワードメッセージです。
get は単項メッセージです。
この例の中に、セミコロンがあります。
これはカスケードと呼ばれるもので
全てのメッセージを 同じオブジェクトに送ります。
一時変数が必要ありません。
そしてよりコンパクトなコードをかけます。
メッセージはあらゆる所にある ということを理解してください。
条件分岐、ループ、列挙、並行処理は メッセージとして表現されます。
これらの 3 つのメッセージについての説明は
あらゆる所で適用されます。
それはシステムの要石なのです。
これらのメッセージ以外には 何もありません。
見てみましょう。
ここに階乗の定義があります。
これをどう定義したらよいでしょう？
factorial メソッドを定義します。
このメソッドにコメントを書きます。 二重引用符を使います。
そして、self で始めます。
もしメッセージを受け取った このオブジェクトがゼロならば
1 を返します。
もし self が正ならば
例えば factorial 6 ならば self = 6 です。
もしもこれが true であれば 何を返したら良いでしょう？
6 かける 6 ひく 1 の階乗
この再帰的な定義はわかっています。 それだけのことですが
ここで注目すべきところは
条件分岐である ifTrue: は
メッセージだということです。 コロン付きのキーワードメッセージで
真偽値に送られています。
同様に ifFalse:ifTrue: や ifTrue:ifFalse: もあります。
これらの条件分岐は
メッセージです。
前に見せたのと同じような キーワードメッセージです。
つまり、条件分岐はメッセージです。
ループもメッセージです。
1 から 4 までのループを作ると
1 to: 4 do:
そしてブロック。 匿名メソッドです。
ここで、i の値を表示したいと言っています。
そして 1, 2, 3, 4 という値を取ると。
見ての通り、to:do: は
キーワードメッセージです。
loop の形をとったメッセージです。
Pharo には他にもループがあります。 timesRepeat: や to:by:do: などです。
それら全てを見ていきます。
しかし、もう一度言いますが これらはメッセージです。
to:do: はオブジェクト 1 に 4 と ブロックを引数として送られます。
ブロックについてはすぐ後で説明します。
イテレーターもあります。
イテレータは別のものです。
メッセージ do: を
コレクションに送って
各要素に対して何を適用するかを言います。
各要素ごとに 関数の引数は
1, 2, -4, -86 という値を取ります。
そしてここでやっていることは
各要素について 絶対値を求めて 表示することです。
また言いますが これは別のコースでやります。
イテレータを説明します。
イテレータは Java 8 にもありますが
Pharo の中核の一部になっています。
ブロックとは何かというと
ブロックは関数に似ています。
数学では f(x) = x²+3 と書きますが
このように書きます。
ブロックを代入する変数を定義します。
ブロックは角括弧の内側です。
ここではブロックには引数が 1 つあります。 x です。
そして本体を書きます。 x+3 です。
このブロックを実行するには
関数の適用です。
これは関数の定義です。 ここで適用します。
ブロックに value: メッセージを送ります。 value: 2 と書きます。
x は 2です。 したがって、ブロックは 5 を返します。
いいですか？
ブロックとは、一種の匿名関数です。 名前がありません。
実際には、ブロックはレキシカルクロージャです。
それを説明します。
ブロックは本物のオブジェクトです。
メソッドの引数として渡されたり 変数に入れられたり
返り値として返されます。
したがって、ブロックは
ウェブアプリケーションでの ボタンのコールバックに使われます。
ブロックの使い方を見てきました。
イテレーターにはブロックを使います。
ブロックは条件分岐に使われることも 見てきました。
後でブロックについての講義があります。
ブロックはエレガントです。 Eiffel で導入され
最近 Java 8 に導入されました。
C# にもあります。
とても基礎的なものです。
ブロックは Pharo の構文や計算モデルの
とても基礎的な要素です。
Pharo ではどうやってクラスを 定義するのでしょう？
ここにあるブラウザは パッケージを表示しています。
その内部にクラスがあります。
テンプレートを表示します。
テンプレートは、 デフォルトで Object から継承すること
クラスの名前
例えば Point クラス
そしてクラス定義
クラスオブジェクトがあり そしてメッセージがあります！
メッセージは subclass:InstanceVariableNames:
なんたらかんたら
これを使って
Point クラスを定義すると
インスタンス変数に x と y を入れます。
見せたいことは、構文が常にメッセージと 同じモデルに従っているということです。
通常、手で書くことはありません。
ツールがテンプレートを渡して あなたはそれを埋めるだけです。
ではメソッドはどうやって定義するのでしょう？
前に言いましたが、メソッドは public で virtual です。
そしてデフォルトで self を返します。
ブラウザの中にいるときは
ブラウザがテンプレートを出します。
メソッドの名前、そして コメント…
我々はお行儀よく親切に コードにコメントを書きます。
一時変数の名前や文を 書き入れます。
これでどうなるのでしょう？ factorial メソッドを見ました。
この場合、Integer クラスにいます。
factorial メソッドを見ると そこにコードがあります。
メソッド名 コメント
そしてメソッド本体が定義されています。
まとめると、何をやったかというと
メッセージには 3 種類あります。 引数のない単項メッセージ
セレクターが数学記号の二項メッセージ
そして複数の引数を取ることができる キーワードメッセージです。
優先順位があります。 最初に括弧
そして単項、二項、そしてキーワードです。
そして同じレベルのメッセージは 左から右へ。
見てきた通り 構文はとてもコンパクトです。
構文要素は少ししかありませんが 本当に表現力が高いです。
構文要素は主にメッセージと レキシカルクロージャ（ブロック）です。
メッセージは 3 種類です。
言語を開発する演習問題をすることになります。
いわゆるドメイン特化言語（DSL）を定義します。