エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

Ioが面白い・その0 準備運動

「7つの言語 7つの世界」を読みました。

7つの言語 7つの世界

7つの言語 7つの世界

Ioが面白いです。もっとも検索しにくいプログラミング言語のひとつ(らしい)。かつて「るびま」で紹介されていて存在だけは知っていたんですがそのときはピンときませんでした。
いま改めて触れてみて。変態さ(失礼)と実用性を兼ね備えた面白い言語だと感じです。


しばらく勉強ノートを書き散らかしていこうかと。

ちなみに。「Io」だと検索しにくいのでタグは「Iolanguage」にしときます。

「1日目」

7つの言語 7つの世界」では各言語を3日で俯瞰するという体裁を取っています。まずはその構成にそって基本の学習。


IoをREPLモードで実行。数字はバージョン番号(というかそのバージョンのリリースの日付)です。

$ io
Io 20110905
Io> 


文字列を表示する。

Io> "Hi ho, Io" println
Hi ho, Io
==> Hi ho, Io

文字列のオブジェクト"Hi hi, Io"printlnメッセージを送っています。オブジェクトはprintlnメッセージを受け取ると自分自身を出力して改行します。結果(式の値)は自分自身(このばあい、もとの文字列)です。


新しい型(type)のオブジェクトを作る。

Io> Vehicle := Object clone
==>  Vehicle_0x473b40:
  type             = "Vehicle"

オブジェクトはプロトタイプとなるオブジェクトのクローンとして作成します。プロトタイプのオブジェクトにcloneメッセージを送るとクローンのオブジェクトを作成します。このとき、名前に大文字から始まる識別子を使うとtypeスロットに名前が入ります。

Io> Vehicle type
==> Vehicle


小文字から始まる名前だとtypeは設定されません。

Io> vehicle := Object clone
==>  Object_0x3afda0:

Io> vehicle type
==> Object


オブジェクトのスロットに値を代入する。

Io> Vehicle description := "Something to take you place"
==> Something to take you place


Ioの代入演算子は標準で3種類あります。

演算子 対応するメソッド 内容
::= newSlot あらたにスロットとセッターを作り、指定された値を代入する
:= setSlot あらたにスロットを作り、指定された値を代入する
= updateSlot 既存のスロットに、指定された値を代入する


演算子とメソッドの対応付けはOperatorTableで確かめることができます。

Io> OperatorTable
(中略)
Assign Operators
  ::= newSlot
  :=  setSlot
  =   updateSlot
(後略)

ちなみに。OperatorTableは特別なオブジェクトなのか、2012/03/03現在、リファレンスのなかに説明を見つけることができません。


::=演算子を使うと、たとえばここではfooというスロットの他にセッターであるsetFooというスロットも作成され、そのスロットに値が代入されます。

Io> Vehicle foo ::= "FOO"
==> FOO
Io> Vehicle
==>  Vehicle_0x473b40:
  description      = "Something to take you place"
  foo              = "FOO"
  setFoo           = method(...)
  type             = "Vehicle"

setFooの中身はこうなっていてfooに値を設定したあと自分自身(ここではVehicleオブジェクト)を返しています。

Io> Vehicle getSlot("setFoo")
==> # doString:1
method(
    foo = call evalArgAt(0); self
)


:=演算子を使うと、スロットを作成しそのスロットに値が代入されます。

Io> Vehicle bar := "BAR"
==> BAR
Io> Vehicle
==>  Vehicle_0x473b40:
  bar              = "BAR"
  description      = "Something to take you place"
  foo              = "FOO"
  setFoo           = method(...)
  type             = "Vehicle"


=演算子は既存のスロットに値を代入します。新たにスロットを作成しないので存在しないスロットに代入しようとすると例外が発生します。

Io> Vehicle foo = "FOOOOOOOOOO"
==> FOOOOOOOOOO
Io> Vehicle baz = "BAZ"

  Exception: Slot baz not found. Must define slot using := operator before updating.
  ---------
  message 'updateSlot' in 'Command Line' on line 1


現在のVehicleのスロットの状態の確認。

Io> Vehicle slotNames
==> list(foo, bar, setFoo, type, description)


Vehicleを継承したCarオブジェクトを作る。

Io> Car := Vehicle clone
==>  Car_0x500a90:
  type             = "Car"

Vehicleにはcloneというスロットはありませんが、VehicleObjectを継承しているのでObjectcloneが実行されます。
Carも大文字から始まっているので、typeスロットが作られています。

Io> Car slotNames
==> list(type)


Cardescriptionメッセージを送ります。

Io> Car description
==> Something to take you place

(継承元の)Vehicleで設定されているdescriptionの値が得られます。


Carのクローンを作ります。

Io> ferrari := Car clone
==>  Car_0x4315d0:

このばあい、名前が大文字から始まっていないのでtypeスロットは作られません。

Io> ferrari slotNames
==> list()

ferrariオブジェクトはスロットをひとつも持っていない)


ferrariオブジェクトのtypeを調べると、継承元のCartypeが使われます。

Io> ferrari type
==> Car

見た目、クラスとインスタンスのような関係になります(あくまで見た目上ですが)。


メソッドは次のように作成します。

Io> method("So, you've come for an argument." println)
==> method(
    "So, you've come for an argument." println
)

ここで作成されたメソッドもまたオブジェクトです。

Io> method("So, you've come for an argument." println) type
==> Block

type[http://www.iolanguage.com/scm/io/docs/reference/index.html#/Core/Core/Block:title=Block]のようです。


オブジェクトなのでスロットに代入できます。

Io> Car drive := method("Vroom" println)
==> method(
    "Vroom" println
)

スロットに代入されたメソッドは、当然そのスロットを持つCarから実行ますが、Carをプロトタイプに持つオブジェクトからも実行できます。

Io> ferrari drive
Vroom
==> Vroom


オブジェクトのプロトタイプはprotoで調べることができます。

Io> ferrari proto
==>  Car_0x365550:
  drive            = method(...)
  type             = "Car"

Io> Car proto
==>  Vehicle_0x348730:
  bar              = "BAR"
  description      = "Something to take you place"
  foo              = "FOOOOOOOOOO"
  setFoo           = method(...)
  type             = "Vehicle"

Io> Vehicle proto
==>  Object_0x300530:
(スロット多数のため省略)


マスター名前空間Lobbyというオブジェクトになります。ここまでで使ってきたCarferrariは、Lobbyのスロットとして管理されています。

Io> Lobby
==>  Object_0x30f810:
  Car              = Car_0x365550
  Lobby            = Object_0x30f810
  Protos           = Object_0x30f780
  Vehicle          = Vehicle_0x348730
  _                = Object_0x30f810
  exit             = method(...)
  ferrari          = Car_0x36ce70
  forward          = method(...)
  set_             = method(...)



…長くなったので、続きはまた後ほど。