7 つの言語 7 つの世界 第 3 章 Io 言語 1-3 日目のセルフスタディやってみた

1日目

探してみよう

Io のいくつかの問題点の例

  • 名前を Google で検索しにくい
  • コミュニティが小さく OS の最新バージョンでしかテストされていない→id:passingloop:20110908:p1

質問に答えてくれる Io コミュニティ

英語だと http://tech.groups.yahoo.com/group/iolanguage/ があります.
少なくとも日本語の質問に答えてくれる Io コミュニティは見つかりません.

Io のイディオムに関するスタイルガイド

英語だと Io Programming/Io Style Guide - Wikibooks, open books for an open world があります.
日本語のスタイルガイドは見つかりません.

確認してみよう

1 + 1 を評価してから,1 + "one" を評価する.Io は強く型付けされた言語か,それとも弱く型付けされた言語か? コードを書いて答えを確かめてみてほしい.

確かめてみました.

Io> 1 + 1
==> 2
Io> 1 + "one"

  Exception: argument 0 to method '+' must be a Number, not a 'Sequence'
  ---------
  message '+' in 'Command Line' on line 1

答: 型の不一致に対して例外を投げているので Io は強く片付けされた言語です.

0 は真か偽か? 空文字列はどうか? nil は真か偽か? コードを書いて答えを確かめてみてほしい.

確かめてみました.

Io> 0 and true
==> true
Io> "" and true
==> true
Io> nil and true
==> false

答: 0 と "" は真,nil は偽です.

プロトタイプに存在するスロットを確認するにはどうすればよいか?

答: proto slotNames を使います.

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

Io> Vehicle description := "Something to take you places"
==> Something to take you places
Io> Vehicle slotNames
==> list("type", "description")
Io> Nissan := Vehicle clone
==>  Nissan_0x10039eaf8:
  type             = "Nissan"

Io> Nissan proto slotNames
==> list("type", "description")

=(等号),:=(コロン等号),および::=(コロンコロン等号)の違いは何か?それぞれどのようなときに使うか?

答: 次の表に整理して説明します.

= スロットが存在すれば代入,スロットが無ければ例外
:= スロットを作成して代入
::= スロットを作成して代入,スロットの setter も同時に作成
試してみよう

ファイルから Io のプログラムを実行せよ

ファイルの例として hello_world.io というファイルを用意します.

この,hello_world.io をコマンドラインから実行します.

$ io_static hello_world.io
Hello, world

スロットの名前を指定して格納されているコードを実行せよ.

getSlot で名前を指定して,call で実行します.

2日目

試してみよう

フィボナッチ数列は 2 つの連続する 1 で始まる.以降,それぞれれの数は直前の 2 つの数の和になっている.1, 1, 2, 3, 5, 8, 13, 21,... という具合ただ.フィボナッチ数 列の n 番目の数を見つけるプログラムを書け.例えば,,fib(1) は 1,fib(4) は 3 となる.また,この問題を再帰とループを用いて解け.

答: 再帰版:

実行結果:

% io_static fib_rec.io
1
3
21

ループ版

実行結果:

% io_static fib_loop.io
1
3
21

分母がゼロのときゼロを返すように/演算子を変更するには,どうすればよいか.

まず,数値の型を調べてみます.

Io> 0 type
==> Number
Io> Number getSlot("/")
==> Number_/()
Io> Number getSlot("divide")
==> nil

Number に divide スロットは無いようなので,元の / を divide に移動して,新しい / を定義します.

実行結果:

% io_static zero_division.io 
0
1.6666666666666667

2 次元配列のすべての要素の数値の総和を求めるプログラムを書け.

答: flatten sum

Io> list(list(1, 2), list(2, 3, 4), list(6, 7)) flatten sum
==> 25

リストに,そのリストのすべての数値の平均を算出するスロット myAverage を追加せよ.リストに数値が含まれていない場合は何が起こるか? (おまけ:リスト内に数値以外の項目を見つけたら,Io 例外を発生させるようにしてみよ.)

答: 平均を算出するだけでいいのなら,

Io> List myAverage := List getSlot("average")
==> # io/A3_List.io:7
method(
    self sum / self size
)
Io> list(1, 2, 3, 4) myAverage println
2.5
==> 2.5

答(おまけ):

2 次元リストを実現するプロトタイプを書け.dim(x, y) メソッドは,要素数が x のリスト y のリストを割り当てる.set(x, y, value) はリストに値を設定し,get(x, y) はリストの値を取得する.

答: 行列を 1 次元リストで表現してみました.次の問題で苦労しそうです.

ボーナス問題: (new_matrix get(y,x)) == matrix get(x,y) が成立するように,元のリストの転置メソッドを書け.

答: 全然ボーナスではなかったです.

実行結果:

% io_static transpose.io
foo
foo

行列をファイルに書き出し,ファイルから行列を読み込め.

答: 今度は 2 次元リストをリストのリストで表現してみます.

実行結果:

% io_static file_matrix.io
foo
bar

1~100 の数のなかからランダムに数を 1 つ 取り出し,それを 10 回以内に当てさせるプログラムを書け.できれば,2 回目以降前回より正解に近づいたか遠ざかったかをヒントとして与えるようにしてみよ.

答: MacPorts で Io をインストールすると,Random が使えずに詰みました → Mac OS X への Io のインストール - passingloopの日記

実行結果: 偶然ですが正解できました.

% io_static quiz.io
input (1-100) > 50
input (1-100) > 51
closer
input (1-100) > 70
closer
input (1-100) > 85
further
input (1-100) > 80
closer
input (1-100) > 75
correct

3日目

本文に掲載した XML プログラムを改良して,インデントを示すスペースを追加するようにしてみよ.

答:

実行結果:

% io_static builder_with_indent.io 
<ul>
  <li>
    Io
  </li>
  <li>
    Lua
  </li>
  <li>
    JavaScript
  </li>
</ul>

角括弧を使ったリスト構文を作成せよ.

答: squareBrackets を使うだけでできました.DSL をつくりたくなりますね.

実行結果:

io_static list.io
List
list("foo", "bar", "baz")

本文に掲載した XML プログラムを改良して属性を処理できるようにしてみよ.具体的には, 第 1 引数がマップ(丸括弧構文を使用)の場合は, それらの各属性を XML プログラムに追加する.次に例を示す.

book({"author": "Tate"}...) と書くと, と出力される

答:

実行結果:

% io_static builder_with_attributes.io 
<book "Author"="Tate">
<ul>
<li>
Io
</li>
<li>
Lua
</li>
<li>
JavaScript
</li>
</ul>
</book>