vieweditattachhistoryswikistopchangessearchhelp

Io

アイオー。プロトタイプベース・オブジェクト指向言語のひとつ。IoLanguage でググるとヒットしやすい。メッセージ送信メタファとしてのオブジェクト指向としては現在の Smalltalk よりある意味純粋で、古の Smalltalk-72 を彷彿とさせる。SELF と NewtonScript (プロトタイプベース)、Act1 (アクター理論)から影響を受けていて、当然、両者の師匠格で同時に反面教師的存在でもある Smalltalk からの影響も大きい…ハズ。

文法面で ALGOL 系にひよってしまっている点では Ruby と同じだが、メッセージ送信モデルに立脚していて、メッセージ自体もエンティティとしてきちんと整備しているぶん、個人的な趣味としては Ruby より好感が持てる。設計者が Smalltalk に敬意を表しているし…(^_^;)。当初は Ruby ほど安定しては動かずがっかりさせられることが多かったが、最近は大幅に改善されつつありプロトタイプベース・オブジェクト指向に対する認知が広まり、それが得意とする問題領域が開拓されるようになれば、大化けするかも。--sumim


インストールと起動

Cygwin (IoVM のみ)、Mac OS X (IoVM, IoDesktop)で動作確認できました。なお、Cygwin はデフォルトで make をインストールしないので、setup.exe で Devel カテゴリから make と gcc をチェックしてインストールする必要があります。 --sumim

基本機能のみ

  1. ダウンロードページより VM のソース(IoVM-2003-12-12.tar.bz2) を get 。
  2. bzip2 -d IoVM-2003-12-12.tar.bz2 で .tar に。
  3. tar xvf IoVM-2003-12-12.tar で展開。
  4. IoVM-2003-12-12 に移動して ./configure して make 。
  5. IoVM に移動して、./io で起動。

デスクトップアプリ用パッケージ(基本機能も含まれます)

  1. ソース (IoDesktop-2003-12-12.tar.bz2) を get 。
  2. 展開
  3. IoDesktop-2003-12-12 に移動して、./configure して make 。
  4. IoDesktop に移動して、./IoDesktop test.ioデモ


サンプルスクリプト

ごく基本

3 + 4
7 を出力。3 がレシーバ、+(4)がメッセージ。この場合、パラメータを括る ( ) は省略できる。
3 + 4 * 5
Smalltalk (7 * 5 で 35 を出力)と異なり、一般的な 23 を出力。ただし一方で (3 + 4) * 5 がエラーになるなど問題も。どうやら、レシーバを括弧でくくってはいけないらしい。パーサーを見ていないので分かりませんが(見ても C は分かりませんが(^_^;))おそらく ( ) で括ると引数扱いになってしまうのかな、と。
"Hello, World!" print
"Hello, World!" を出力。"Hello, World!" がレシーバ、print がメッセージ…だと思ったら、"Hello, World!" もメッセージ(everything is a message)、という可能性もありそう。要調査。

階乗

Number factorial = method(if(self < 2, 1, n = self - 1; self * n factorial))
10 factorial
なぜか常に 0 を返すデフォルトの Number >> factorial をオーバーライドしてみる。3628800 を出力。self * (self - 1) factorial とできないのツライところ。bignum はサポートしていないらしいが、ある程度までは答えを出してくる。

[あ、例の意味を半減させてしまってすいません。ライブラリなんかが多少バグっててもユーザが勝手に修復できる、というのはプロトタイプベースやら特異メソッドの意外な強みですねえ…ところで、はじめまして、ご紹介ありがとうございます。 --shinichiro.h]

[>例の意味
とんでもございません。アクティブなコミット、頭が下がります。どんどんバグがとれて、より多くのかたに楽しみながら役立ててもらえる言語・処理系になるといいですね。--sumim]

委譲

Application = Object clone;
Application preview = method("preview in Application\n" print);
Window = Object clone;
Window printOut = method("print out in Window\n" print);
Button = Object clone;
Button help = method("help in Button\n" print);

application = Application clone;
window = Window clone;
window parent = application;
button = Button clone;

button parent = window;

button help;
button printOut;
button preview;
HMDT の Chain of Responsibility の NewtonScript 版を Io で焼き直したもの。Object clone の記述の繰り返しが若干ウザイ(未定義の変数はデフォルトで Object のクローンにするとかで回避できないか)が、それを含めて素直に見たまま何をしたいのかが分かってよろしげ。「help in Button」「print out in Window」「preview in Application」を順に出力。

Self チュートリアルの BankAccount

BankAccount = Object clone
BankAccount dollars = 200
BankAccount dollars
==> 200
BankAccount deposit = method(x,
   dollars = dollars + x)
BankAccount deposit(50)
==> 250
BankAccount withdraw = method(x,
   dollars = 0 max(dollars - x))
BankAccount withdraw(100)
==> 150
BankAccount withdraw(200)
==> 0
account = BankAccount clone
account dollar
==> 0
account print

Object_0x1c71e0
(
  proto = Object_0x147b00   # まだ proto の dollars を参照している
)

account deposit(500)
==> 500
account print

Object_0x1c71e0
(
  dollars = 500   # 自らの dollars を新設してそこに数値を設定
  proto = Object_0x147b00
)

BankAccount dollars
==> 0   # proto の dollars には影響なし

StockAccount = BankAccount clone
StockAccount numShares = 10
StockAccount pricePerShare = 30
StockAccount dollars = method(x,
   if(x, numShares = x / pricePerShare; dollars, numShares * pricePerShare))
StockAccount dollars   # 引数がなければ株数、株単価から計算
==> 300
StockAccount dollars(150)   # 引数があれば、株単価から株数を算出し設定
StockAccount numShares
==> 5   # 株数値が変更されている
stock = StockAccount clone
stock dollars(600)
stock numShares
==> 20
Self の Demo.snap にある BankAccount のデモを Io 向けに焼き直し。
ここまではなんとかトリッキーなことをしてしのいだが、この後、stock deposit(60) などとすると破綻する。
Self ではスロット(インスタンス変数に相当)の名前をそのままゲッターとして使える。
この点では Io も同じだが、Self はさらに同名で“:”付きのメッセージセレクタをセッターとして使えるのに対し、Io はこの機能を(記法上の制約から)欠いている。
これは Self の便利さに引き替えの制約(スロット名と同名のメソッドを作れない)に加えて、Io は、やはり従来の ALGOL 系記法を読み慣れた人のとっつきやすさと引き替えに、スロット名と同名(+“:”)のメソッドを作れないという二重苦を背負っていることを意味する。
つまり、slot というスロット(Smalltalk はインスタンス変数)があるとき、
ことを意味する。したがって、スロット名メッセージでのスロットへのアクセス、スロットへの代入文“=”での値セットは一見、便利そうにみえるが、それは単に public であるがゆえの便利さであって、継承(委譲)のニーズを考えると結局、getなんたら、setなんたらのようなメソッドを別途用意しないといけない。(同時に、Smalltalk で Direct Variable Access SBPP p.99 が推奨される局面があるように、使い捨てのスクリプトを書くための言語だから、そうした配慮はいらないという見方も当然ありうる。)
BankAccount の例でこれを実践すると、
BankAccount = Object clone
BankAccount dollars = 200
BankAccount dollars
==> 200
BankAccount getDollars = method(dollars)
BankAccount setDollars = method(x, dollars = x)
BankAccount deposit = method(x, setDollars(getDollars + x))
BankAccount deposit(50)
==> 250
BankAccount withdraw = method(x, setDollars(0 max(getDollars - x)))
BankAccount withdraw(100)
==> 150
BankAccount withdraw(200)
==> 0
account = BankAccount clone
account getDollars
==> 0
account print

Object_0x25ac80
(
  proto = Object_0x23e3e0   # まだ BankAccount の dollars を参照している
)

account deposit(500)
==> 500
account print

Object_0x25ac80
(
  dollars = 500   # 自らの dollars を新設してそこに数値を設定
  proto = Object_0x23e3e0
)

BankAccount getDollars
==> 0   # proto の dollars には影響なし

StockAccount = BankAccount clone
StockAccount numShares = 10
StockAccount getNumShares = method(numShares)
StockAccount setNumShares = method(x, numShares = x)
StockAccount pricePerShare = 30
StockAccount getPricePerShare = method(pricePerShare)
StockAccount setPricePerShare = method(x, pricePerShare = x)
StockAccount getDollars = method(getNumShares * getPricePerShare)
StockAccount setDollars = method(x,
   setNumShares(x / getPricePerShare); getDollars)
StockAccount getDollars   # ゲッターを使用
==> 300
StockAccount setDollars(150)   # セッターを使用


StockAccount getNumShares
==> 5   # 株数値が変更されている
stock = StockAccount clone
stock setDollars(600)
stock getNumShares

==> 20
stock deposit(60)  # “=”をセッターに使うと StockAccount >> dollars(getDollars 相当)が破壊されてしまっていた
==> 660
stock getNumShares
==> 22
stock withdraw(120)
==> 540
stock getNumShares
==> 18
のようになり、話の流れを完結できる。参考までに、Self の GUI を使わない CUI 版はこんな感じ。Self の GUI 版は ここいらへん [英語]。Smalltalk の例はこちら。ここまで--sumim

Ruby でもクラス変数とクラスメソッドを使ってプロトタイプベース・オブジェクト指向スクリプティングを試してみています。っても、Smalltalk のプロトタイプベース的スクリプティングの単なる移植ですが。--sumim



Io FAQに『Ioは「アイ・オー(eye-oh)」と発音します。』って書いてありますね。 -- seeds

ご指摘感謝。直しました。--sumim

ふと、「あれ?」と思ったので、googleのキャッシュをみてみたのですが、昔は
「『(i-oh)』と発音します」などと書いてあったようでした。結局どっちだかさっぱり
わからなかった覚えがあります。 -- 2

おそらくは、eye と発音させたかったのに、i と書いてしまってはそれが伝わらなかった…というところではないでしょうか。 実際、私もイオだと思っていましたし。--sumim

『私の好きな木星の衛星のひとつ。』とも書いているので混乱しますね(笑)
もしくはGo ComputerのEO(イーオー)と混乱しないような配慮とか?(それはないか) --- seeds

このページを編集 (10379 bytes)


Congratulations! 以下の 8 ページから参照されています。

This page has been visited 11920 times.