Scilabでは演算子オーバーロードができます。そのメカニズムは原始的ですが、素朴で分かりやすいとも言えます。Scilabに興味がなくても、オーバーロードに興味がある方には面白い話だと思います。
Scilabはたくさんの演算子記号を持っています。それらの演算子記号の意味を、ユーザーは拡張することができます。論理否定演算子「~」を例にしましょう。
--> ~%T ans = F --> ~0 ans = T --> ~"hello" 指定したオペランド用の演算子が未定義です. オーバーロード用の関数 %c_5 を確認または定義してください.
%T(真を表す定数)の論理否定はF(偽)です。論理否定演算子「~」は数値0に対しても使えて、0の否定はT(真)となります。しかし、論理否定演算子「~」を文字列には使えません。
文字列"hello"の否定に対してエラーメッセージが出てますが、このエラーメッセージが演算子オーバーロードに対する適切なアドバイスになっています。関数 %c_5 を定義すればオーバーロードができるのです。
と言ってもまだ謎ですよね。説明しましょう。Scilabの式に演算子が出現した場合、Scilab組み込み演算子と解釈できるなら何ら問題はありません。そうでないとき、Scilabインタプリタは演算子に対応するユーザー定義関数を探すのです。対応する関数が見つかればそれを実行します。
演算子に対応する関数の名前は前もって約束されています。ネーミングルールがあるのです。そのルールは help overloading コマンドで見ることができます。インターネット上なら https://help.scilab.org/docs/6.0.0/en_US/overloading.html です。
まず、演算子記号には、英数字1文字の“コード”が決まっています。overloadingヘルプに記号とコードの対応表がありますが、最初の幾つかを挙げると:
演算子記号 | コード |
---|---|
' | t |
+ | a |
- | s |
* | m |
/ | r |
記号コードだけでは不十分で、データ型もコード化する必要があります。実際、型コードも決まっています。型コードは1文字から4文字の英字です。またヘルプから最初の幾つかを挙げると:
データ型 | コード |
---|---|
数値行列 | s |
多項式行列 | p |
論理値行列 | b |
疎行列 | sp |
記号コードと型コードの組み合わせ方のルールは以下のとおりです。
論理否定演算子を文字列データに対して定義したいならば:
- %文字列の型コード_論理否定の記号コード
という名前の関数を定義します。ヘルプで調べれば分かりますが、先のエラーメッセージに、
- オーバーロード用の関数 %c_5 を確認または定義してください.
とありました。これを見ればすぐに分かります。
- 文字列の型コードは c
- 論理否定の記号コード 5
ではさっそく関数 %c_5 を定義してみます。
function ret = %c_5(str) ret = strrev(str) // 文字列をひっくり返す endfunction
関数 %c_5 を定義した後では、
--> ~"hello" ans = olleh --> ~"live" ans = evil
「~」演算子が文字列をひっくり返す演算として使えるようになりました。回文のチェックに使えます、日本語もOK。
--> ~"madam Im adam" ans = mada mI madam --> ~"たけやぶやけた" ans = たけやぶやけた
二項演算子もやってみます。
--> "hello"*5 指定したオペランド用の演算子が未定義です. オーバーロード用の関数 %c_m_s を確認または定義してください.
もうお分かりですね。
- 文字列の型コードは c
- 乗法の記号コード m
- 数値の型コードは s
なので、文字列と数値を引数に取る関数 %c_m_s を定義すればいいわけです。
function ret = %c_m_s(str, n) ret = '' for i=1:n do ret = ret + str end endfunction
--> "hello"*5 ans = hellohellohellohellohello --> "イヤ"*2 ans = イヤイヤ
文字列を指定回数だけ繰り返す演算子「*」が定義できました。