【MaxScript】引数の参照渡し

2017年9月2日

MaxScriptにおける引数の参照渡しについて。

引数が数値の場合

まず通常の値渡しで数値を受け取る関数を作ってみます。

function test i = (
    i += 1
)

これを実行すると以下のようになります。

valとして1を与えた変数をtest関数に渡しました。test関数は受け取った引数に1を加算して返します。

このとき、関数内で使われた変数iには、引数として渡したvalがコピーされて実行されます。そのため関数の実行後もval自身の値は変化しません。

対して参照渡しの場合、関数定義を変更します。

function testRef &i = (
    i += 1
)

これを実行すると以下のようになります。

参照渡しの関数を定義する際は、仮引数に&をつけて定義します。またこの関数を呼び出す際にも、引数に渡す変数に&をつけて渡します。

このような関数を実行すると、参照渡しで渡した引数は関数の中で変更されると元の変数も変化します。関数の実行時にコピーされるのではなく、そのまま元の変数が使われるようなイメージです。(実際には参照として渡す、という操作が行われていますが元の変数がそのまま変更されるという点を理解しておけば良いでしょう)

引数が文字列の場合

他の型の引数でも同様のことをやってみましょう。文字列の場合は次のようになります。

function test s = (
    s += "_modified"
)

function testRef &s = (
    s += "_modified"
)

これを実行してみます。

このように、文字列の場合でも同様に値渡しでは関数の中で引数がコピーされ、コピーの方に処理が行われます。

数値の場合はそれほどメモリ容量を消費するような大きさにはならないためほとんど問題になりませんが、文字列の場合は、値渡しの関数に巨大な文字列を渡すとメモリ領域を大きく消費する可能性があります。そのため、メモリ効率の観点から、文字列引数を扱う関数を参照渡しで定義したりすることがあります。

引数が配列の場合

引数が配列の場合も見てみましょう。

function test arr = (
    append arr arr.count
)

function test &arr = (
    append arr arr.count
)

これを実行してみます。

実は配列を引数で渡す場合、関数が参照渡しで定義されていなくても参照渡しとして処理されます。この点は注意しておきましょう。関数の引数に配列を渡す場合ほぼ間違いなく元の変数が変更されます

余談ですが、配列を引数に取る関数で元の配列を変更しないようなものも作ることはできます。

function test arr = (
    local tmp = deepcopy arr
    append tmp tmp.count
)

これを実行すると次のようになります。

このように、関数定義内で受け取った配列引数をdeepcopyしてやると、元の変数を変更しない状態で配列を処理することができます。

ただ、このような関数はMaxScriptのビルトイン関数などとも違った動作をすることになるため、使う人を混乱させる元になりかねません。あまりやらないほうが良いでしょう。