1 + 1

| | コメント(4)

mieで1+1を計算するプログラムは次のようになります。


1.+ <+[1]!;
--> 2

きんもーっ☆
…いや、まぁ普通にも書けます。

1 + 1;
--> 2

でなんで 1.+ <+[1]! が 1 + 1 となるのかというところを解説します。

mieでオブジェクトを定義するには次のようにします。


pt = [x = 10, y = 25];

これでx,y成分を持つ座標オブジェクトptが定義されました。
「名前 = 値」と書いて名前に値を束縛します。
上の式は、xという名前に整数10、yという名前に整数25を束縛したオブジェクトを
ptという名前に束縛する、という意味になります。
xやyに当たるオブジェクトの中身のことを要素と呼びます。

オブジェクトの要素を参照することを抽出と呼びます。
抽出を行なうにはオブジェクトの後にシンボルを記述します。
シンボルのリテラルは「.」で始まります。
よってptオブジェクトの要素xを抽出するには次のように書きます。


pt .x;
--> 10

空白文字は省略できるので、C言語などのメンバ参照と同じ見た目になります。

pt.y;
--> 25

mieではSmalltalkやRuby同様に整数はオブジェクトです。
加減乗除などのメソッドは整数オブジェクトの要素として定義されています。
先程のpt.xの例と同じように、1オブジェクトの要素+メソッドを抽出することができます。


1.+;
--> <builtin:Mie::IntegerObj::Add>

次にオブジェクトの拡張生成について。
ptオブジェクトを2次元から3次元に拡張したい場合、
次のように新たにz成分を追加したオブジェクトを生成できます。


pt <+ [z = 0];
--> [x = 10, y = 25, z = 0]

「<+」はメタ結合と呼び、2つのオブジェクトを重ね合わせたオブジェクトを生成します。

引数を2乗する関数squareを定義してみます。


square = {x|x * x};

引数xを受け取り、xにxを掛けた値を返す、ということです。
ここで{}は基本的には[]と同じで、オブジェクトリテラルです。
主に関数的に利用する場合に使います。
mieでは関数とオブジェクトは全く同等なデータ構造です。

定義されたsquareに対して整数3を要素に持つオブジェクトをメタ結合します。
すると引数(要素)xに3が束縛された状態になります。


square <+ [3];
--> {x = 3| x * x}

この時点ではまだ束縛されただけでx*xは計算されていません。

x*xを計算させるためには評価をする必要があります。
評価は対象となる式の後に「!」と記述します。
3を引数に束縛して、評価すると9が返ってきます。


square <+ [3]!;
--> 9

適用(メタ結合)してから評価する、という2段階で関数実行が行われることになります。
適用+評価はより簡潔に書けます。これはシンタックスシュガーです。
単に空白文字で区切ってオブジェクトを並べると、メタ結合した後に評価が行われます。


square [3];
--> 9

お好みで空白文字を取り除くことも可能です。

square[3];
--> 9

適用と評価が分離しているため、適用後のオブジェクトを一旦変数に保持しておき、
後で評価を行うということも可能です。明示的な遅延評価ですね。
これが役に立つのかどうかはわかりません。


tmp = square <+ [3];
tmp!;
--> 9

さらにもう一つのシンタックスシュガーを紹介します。
名前が演算子文字で始まる要素の場合、


object <element> arg;

と書くと以下のように解釈されます。

object.<element> [arg]

つまり、

1 + 1;

は次のようになります。

1.+ [1]

さらにこれに対して適用+評価のシンタックスシュガーを展開すると

1.+ <+[1]!

となるわけです。
これで、オブジェクト1の要素+メソッドに、要素にオブジェクト1を持つオブジェクトをメタ結合して
評価すると、オブジェクト2が得られました。ふぅー。

ちなみに、squareの例ですが関数リテラルで直接書くと次のようになります。


{x|x * x}[3];
--> 9

これもシンタックシュガーを使わずに書くと次のようになります。

{x|x.* <+[x]!}<+[3]!;
--> 9


なんとなく書けるうちに書いておいて少しでも知ってもらえたらなと。
需要があるようなら定期的に書いていきたいと思います。
わからないところとか気になるところとかコメント頂けると幸いです。

コメント(4)

acht :

見たこともない感じなので新鮮で面白いです。
リリースに向けて定期的に書いて貰えるとありがたいです!

ちなみに、
square = {x|x * x};
square 16
でいいのかな?

ごんし :

はじめてコメントします。
自分はC言語とFORTRANしかかじったことがないので
いつもすごいなぁと感心してしまいます。
でもすごすぎて自分の頭では理解できない。。。

anm :

この辺りは、まあ変わらないとこだよねー。
(つか変わったら実装やりなおしw)

言語は生き物なのでちょろちょろ変わりますが、
こういう文章の需要は大有りです。個人的に。
(卒論の付属資料が豊かになるなあ・・・w)

eclipse :

>>acht
square[16] を
square 16 と書けるのかということでしょうか?
それはできません。
16と[16]は異なるオブジェクトなので。
square 16 としてしまうと
16自体ではなく、16というオブジェクトの中の最初の要素が
squareのxに束縛されてしまいます。
# エラーとしてはじくかもしれませんが

>>ごんしさん
FORTRANとはまた渋いですねぇw
わけわかですか…
用語とかもちっと還元して解説すべきなんでしょうね。

>>anm
>この辺りは、まあ変わらないとこだよねー。
そう願いたいものですw
>こういう文章の需要は大有りです。個人的に。
相方にそう言ってもらえると俄然やる気が湧いてきます!

このブログ記事について

このページは、yuchが2005年11月10日 01:34に書いたブログ記事です。

ひとつ前のブログ記事は「神無月」です。

次のブログ記事は「いまどきのプログラム言語の作り方」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.01