関数パラメータ

関数のパラメータは、関数の本文の冒頭にローカル変数として暗示的に宣言され、呼び出し元によって与えられた引数で初期化されます。パラメータには、関数本体 <expr> の終わりまで広がるスコープがあります。他のローカル変数同様、ネストされたローカル変数に同じ名前で代入したり、そのローカル変数で非表示にすることもできます。

キーワード パラメータは、関数の定義で既定値を与えられ、暗示的に呼び出し元のオプションのパラメータになります。このキーワード引数の 1 つを呼び出し元が提供しないと、キーワード引数は関数エントリ時に既定値に初期化されます。既定値は、 「:」 (コロン)の後に指定されます。

キーワード パラメータが既定値なしで定義され、呼び出し元から提供されていない場合、キーワード パラメータは特殊値 unsupplied に初期化されます。この値を関数の本体で調べることで、必要なキーワード引数がないときに発生するエラーに対処することができます。

fn foo a b: c: d: =
(
if c == unsupplied then print "Where's the c: argument??"
-- ...
)

参照代入」で説明されているように、MAXScript では参照代入と呼ばれる代入が使われます。関数の各パラメータ変数には、呼び出し元によって関数に渡された値への参照が含まれます。パラメータ変数への代入を行うと、パラメータ変数の参照が新しくなりますが、呼び出し元の変数の値には影響はありません(完全にローカルなアクションです)。例外として、パラメータ値が 3D Point、文字列、または配列などの合成値であり、この合成値のコンポーネントの 1 つに新しい値を代入する場合があります。この場合、変数の参照は変化せず、変更した合成値は引き続き呼び出し元の変数で参照されます。

関数で複数の値を取得する場合でも、パラメータ変数の合成値にコンポーネントを代入するのはあまりいい方法とは言えません。パラメータとして渡された合成値を演算するには、呼び出し元で合成値を作成し、関数に渡すことが必要です。次に例を示します。

スクリプト:

fn getXYZset val =
(
val.x=random -100 100
val.y=random 100 100
val.z=random val.x val.y
)
(
v1=[0,0,0]
v4=v1
getXYZSet v1
format "v1= %; v4= %\n" v1 v4
getXYZSet v4
format "v1= %; v4= %\n"v1 v4
)

出力:

getXYZset() -- result lines 1 to 5
v1= [-84,100,78.1224]; v4= [-84,100,78.1224] -- output line 10
v1= [10,100,18.6575]; v4= [10,100,18.6575] -- output line 12
OK -- result lines 6 to 12

渡されるのは一方の変数のみですが、 v1 および v4 変数の両方の値が getXYZset の呼び出し内で設定されるように見えることに注意してください。理由は、8 行目の変数 v4 v1 の値に初期化されるためです。実際には 7 行目で Point3 値への参照[0,0,0]が作成され、この参照が v1 に格納されます。8 行目ではこの同じ参照が v1 から引き出され、 v4 に代入されます。2 つの異なる値を格納するのではなく、 v1 および v4 の両方が同じ値を参照します。 getXYZset で合成値のコンポーネントを設定すると、Point3 値は変更されず、両方の変数とも元の値を参照します。

関数から複数の値を返すには、関数で返される値を配列または構造体にします。たとえば、次のようになります。

スクリプト:

fn readDataFile filename =
(
f=openfile filename
data=#()
avg=0
nVals=0
while not eof f do
(
val = readvalue f
append data val
avg += val
nVals += 1
)
close f
#(data,(avg/nVals))
)
result=readDataFile "c:\\datafiles\\run1.dat"
data=result[1]
avg=result[2]

通常、パラメータとして渡される合成値を演算する関数を作成する場合は、値の コピー を作成します。これにより、呼び出し元内の値が誤って変更されるのを防ぐことができます。たとえば、次のようになります。

スクリプト:

fn uppercase instring =
(
local upper, lower, outstring
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower="abcdefghijklmnopqrstuvwxyz"
outstring=copy instring -- operate on copy of instring
for i=1 to outstring.count do
(
j=findString lower outstring[i]
if j != undefined do outstring[i]=upper[j]
)
return outstring
)