「2日目」のつづき。「2日目」というのは、Ioのエントリを書き始めて2日目という意味でなくて、本の章の名前です。

- 作者: Bruce A. Tate,まつもとゆきひろ,田和勝
- 出版社/メーカー: オーム社
- 発売日: 2011/07/23
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 230回
- この商品を含むブログ (64件) を見る
演算子
OperatorTableオブジェクトに登録することで自作の演算子を使えるようになります。
OperatorTableオブジェクトの作りを見てみると。
Io> OperatorTable
==> OperatorTable_0x348ff0:
Operators
0 ? @ @@
1 **
2 % * /
3 + -
4 << >>
5 < <= > >=
6 != ==
7 &
8 ^
9 |
10 && and
11 or ||
12 ..
13 %= &= *= += -= /= <<= >>= ^= |=
14 return
Assign Operators
::= newSlot
:= setSlot
= updateSlot
To add a new operator: OperatorTable addOperator("+", 4) and implement the + message.
To add a new assign operator: OperatorTable addAssignOperator("=", "updateSlot") and implement the updateSlot message.
通常の演算子(Operators)と代入演算子(Assign Operators)の一覧が表示され、ご丁寧なことに登録の仕方も表示されます。通常の演算子であればaddOperatorメソッドを使えばよいようです。数字は結合の優先順位です。
本にならって真偽値の排他的論理和xorを定義してみます。
まず演算子xorを登録します。
Io> OperatorTable addOperator("xor", 11)
==> OperatorTable_0x348ff0:
Operators
(中略)
11 or xor ||
(後略)
次に実装。昨日のエントリでも書いたように真偽値の演算は真偽値をあらわすオブジェクトtrue、falseのメソッドとして実装されています。
実装。
Io> true xor := method(cond, if(cond, false, true))
==> method(cond,
if(cond, false, true)
)
Io> false xor := method(cond, if(cond, true, false))
==> method(cond,
if(cond, true, false)
)
実行結果。
Io> false xor false ==> false Io> false xor true ==> true Io> true xor false ==> true Io> true xor true ==> false
ここでちょっと疑問。演算子を登録しないでメソッドだけ設定したらどうなるのか?
インタプリタを起動しなおして。true xorとfalse xorを上と同じように設定。
実行結果。
Io> false xor false ==> false Io> false xor true ==> true Io> true xor false ==> false Io> true xor true ==> true
さてなにが起こったのか。
xorを次のようにしてみて引数の様子を見てみます。
Io> true xor := method(cond, ("cond = " .. cond) println; if(cond, false, true))
==> method(cond,
("cond = " .. cond) println; if(cond, false, true)
)
Io> false xor := method(cond, ("cond = " .. cond) println; if(cond, true, false))
==> method(cond,
("cond = " .. cond) println; if(cond, true, false)
)
実行結果。
Io> false xor false cond = nil ==> false Io> false xor true cond = nil ==> true Io> true xor false cond = nil ==> false Io> true xor true cond = nil ==> true
引数の値はいずれもnil、つまり引数なしと扱われています。
これはつまり、true xor trueは(true xor()) trueと解釈されるということのようです。true xorは引数condがnilになるためtrueを返します。このためtrue trueという式になるのですが、任意のオブジェクトにtrueを送るとtrueが返るようです。falseについても同様。
Io> Object true ==> true Io> Object false ==> false
このため全体としては式の末尾の真偽値がそのまま式の値となる、ということのようです。
ところで。
演算子には+とか*とかあるじゃないですか。そいう記号を使った演算子を作りたいばあいどうするのか?
たとえば不一致を評価する演算子に!=の替わりに<>を使いたいとか思ったとき、どうすればいいか。
答え。<>にメソッドを設定すればOK。
Io> OperatorTable addOperator("<>", 6)
(略)
Io> Object <> := method(arg, self != arg)
==> method(arg,
self != arg
)
実行結果。
Io> 1 <> 1 ==> false Io> 1 <> 2 ==> true
ちなみに。今回のように別のメソッドとまったく同じ動作をするものを用意したいとき、上記のようにメソッドを定義する替わりに値をそのまま借りてしまうという方法があります。
Io> Object <> := Object getSlot("!=")
==> Object_!=()
この例では。!=の値を取り出してそのまま<>に設定してしています。
記号もスロット名に使えるとなると、こんなこともできてしまいます。
Io> 5 factorial
==> 120
Io> Number ! := Number getSlot("factorial")
==> Number_factorial()
Io> 5!
==> 120
Io> 10!
==> 3628800
Io面白いっ!
…「2日目」はまだつづく。