「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日目」はまだつづく。