[1] 関数の定義
ANSI-Cとほとんど同じです。関数名の付け方は、識別子名の命名規則に従います。
例を見たほうが早いと思います。func関数は、2つのint型の値を受け取って、その積を返す関数です。
import std.stdio;
void main(){
writefln("%d",func(150,200));
}
int func(int param1,int param2){
return param1*param2;
}
[2] 関数の属性
ある一定の条件を満たす関数は、特殊な意味を持つことがあります。例えば、外部状態に依存しない関数だったり、例外を投げない関数だったり…
これらには、属性を付加する必要がある場合が多いですが、属性の付加はとても簡単。関数定義の前に、属性を書き加えるだけです。属性は複数付けることができます。要するに、宣言方法は…
属性名… 戻り値 関数名(引数宣言){………
1.pure関数
pure関数とは、同じ引数を渡せば、常に同じ戻り値が帰ってくる関数のことです。要するに、引数以外に依存しない関数のことです。定義は簡単、普通の関数定義の前にpure属性を付けるだけです。pure関数では、次のようなことは出来ません。
・immutable定数ではないグローバル変数や静的変数を読み書きすること (h2so5さんの指摘で判明しましたが、グローバル変数に限らず、関数内で寿命を終える変数以外を使えないということです。ごめんなさい。)
・pureでない関数を呼び出すこと
・入出力を行うこと
ってなわけで、実は、さっきのfunc関数がまさにpure関数の条件を満たすのです。だから、func関数に、何の問題も無くpure属性を付加することが出来ます。
2.nothrow関数
これは、例外を関数外に投げることのない関数のことです。例外については日を改めて説明します。
[3] 関数の引数の属性
関数の引数にも、属性を付けることができます。これらは、引数宣言の型の前に属性名を付けるだけです。これも、互いに矛盾しない限り、複数の属性を付けることができます。
1.in,out,ref属性
これらは、引数の読み書きについて規定するものです。属性の意味は、次の通りです。
import std.stdio;
void main(){
int result;
func(150,200,result);
writefln("%d",result);
}
void func(int param1,int param2,out int result){
result = param1 * param2;
}
► スポイラーを表示
lazy属性は、引数を遅延評価するときに使う属性です。引数を遅延評価するとはどういうことかというと、普通、関数の引数は、関数が呼び出された時点で評価されて、結果の値が関数に渡されますが、評価するタイミングが、引数が関数内部で使われたときに評価されるのです。
import std.stdio;
void main(){
int val1 = 1,val2 = 1;
writeln("call normal function.");
normal_func(++val1);
writeln("call lazy function.");
lazy_func(++val2);
}
void normal_func(int value){
for(int i = 0; i < 10; i++){
writef("%d,",value);
}
writeln();
}
void lazy_func(lazy int value){
for(int i = 0; i < 10; i++){
writef("%d,",value);
}
writeln();
}
call normal function.
2,2,2,2,2,2,2,2,2,2,
call lazy function.
2,3,4,5,6,7,8,9,10,11,
分かりやすい比較だと思いますが、要するに、lazy_func関数のほうでは、++val2という式が、関数内部で呼ばれるたびに評価されているわけです。だから、for文の中で値が増えているわけです。この辺りは、C言語のマクロ引数に似たところがあると思います。
前の記事「比較演算とプログラムの制御文(1)」 ←→ 次の記事「データ型と式のプロパティ(1)、typeof演算子」