Dプログラミング-関数
この章では、Dプログラミングで使用される関数について説明します。
Dでの関数定義
基本的な関数定義は、関数ヘッダーと関数本体で構成されます。
構文
return_type function_name( parameter list ) {
body of the function
}
これが関数のすべての部分です-
Return Type−関数は値を返す場合があります。ザ・return_type関数が返す値のデータ型です。一部の関数は、値を返さずに目的の操作を実行します。この場合、return_typeはキーワードですvoid。
Function Name−これは関数の実際の名前です。関数名とパラメータリストが一緒になって関数シグネチャを構成します。
Parameters−パラメータはプレースホルダーのようなものです。関数が呼び出されると、パラメーターに値を渡します。この値は、実際のパラメーターまたは引数と呼ばれます。パラメータリストは、関数のパラメータのタイプ、順序、および数を参照します。パラメータはオプションです。つまり、関数にパラメータを含めることはできません。
Function Body −関数本体には、関数の機能を定義するステートメントのコレクションが含まれています。
関数の呼び出し
次のように関数を呼び出すことができます-
function_name(parameter_values)
Dの関数タイプ
Dプログラミングは幅広い機能をサポートしており、それらを以下に示します。
- 純粋関数
- Nothrow関数
- 参照関数
- 自動機能
- 可変個引数関数
- Inout関数
- プロパティ関数
各種機能を以下に説明します。
純粋関数
純粋関数は、引数を介してグローバルまたは静的な可変状態保存にアクセスできない関数です。これにより、純粋関数が渡されないものを何も変更しないことが保証されているという事実に基づいて最適化が可能になり、純粋関数がその引数を変更できないことをコンパイラーが保証できる場合は、完全な関数の純粋性を有効にできます。つまり、関数が同じ引数に対して常に同じ結果を返すという保証です)。
import std.stdio;
int x = 10;
immutable int y = 30;
const int* p;
pure int purefunc(int i,const char* q,immutable int* s) {
//writeln("Simple print"); //cannot call impure function 'writeln'
debug writeln("in foo()"); // ok, impure code allowed in debug statement
// x = i; // error, modifying global state
// i = x; // error, reading mutable global state
// i = *p; // error, reading const global state
i = y; // ok, reading immutable global state
auto myvar = new int; // Can use the new expression:
return i;
}
void main() {
writeln("Value returned from pure function : ",purefunc(x,null,null));
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
Value returned from pure function : 30
Nothrow関数
Nothrow関数は、クラスExceptionから派生した例外をスローしません。Nothrow関数は、throw関数と共変です。
Nothrowは、関数が例外を発行しないことを保証します。
import std.stdio;
int add(int a, int b) nothrow {
//writeln("adding"); This will fail because writeln may throw
int result;
try {
writeln("adding"); // compiles
result = a + b;
} catch (Exception error) { // catches all exceptions
}
return result;
}
void main() {
writeln("Added value is ", add(10,20));
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
adding
Added value is 30
参照関数
Ref関数を使用すると、関数は参照によって戻ることができます。これは、ref関数パラメーターに類似しています。
import std.stdio;
ref int greater(ref int first, ref int second) {
return (first > second) ? first : second;
}
void main() {
int a = 1;
int b = 2;
greater(a, b) += 10;
writefln("a: %s, b: %s", a, b);
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
a: 1, b: 12
自動機能
自動関数は、任意のタイプの値を返すことができます。返されるタイプに制限はありません。自動タイプ機能の簡単な例を以下に示します。
import std.stdio;
auto add(int first, double second) {
double result = first + second;
return result;
}
void main() {
int a = 1;
double b = 2.5;
writeln("add(a,b) = ", add(a, b));
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
add(a,b) = 3.5
可変個引数関数
Variadiac関数は、関数のパラメーターの数が実行時に決定される関数です。Cでは、少なくとも1つのパラメーターを持つという制限があります。しかし、Dプログラミングでは、そのような制限はありません。簡単な例を以下に示します。
import std.stdio;
import core.vararg;
void printargs(int x, ...) {
for (int i = 0; i < _arguments.length; i++) {
write(_arguments[i]);
if (_arguments[i] == typeid(int)) {
int j = va_arg!(int)(_argptr);
writefln("\t%d", j);
} else if (_arguments[i] == typeid(long)) {
long j = va_arg!(long)(_argptr);
writefln("\t%d", j);
} else if (_arguments[i] == typeid(double)) {
double d = va_arg!(double)(_argptr);
writefln("\t%g", d);
}
}
}
void main() {
printargs(1, 2, 3L, 4.5);
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
int 2
long 3
double 4.5
Inout関数
inoutは、関数のパラメーターと戻り値の型の両方に使用できます。これは、可変、定数、および不変のテンプレートのようなものです。可変性属性はパラメーターから推定されます。つまり、inoutは、推定された可変性属性を戻り値の型に転送します。可変性がどのように変化するかを示す簡単な例を以下に示します。
import std.stdio;
inout(char)[] qoutedWord(inout(char)[] phrase) {
return '"' ~ phrase ~ '"';
}
void main() {
char[] a = "test a".dup;
a = qoutedWord(a);
writeln(typeof(qoutedWord(a)).stringof," ", a);
const(char)[] b = "test b";
b = qoutedWord(b);
writeln(typeof(qoutedWord(b)).stringof," ", b);
immutable(char)[] c = "test c";
c = qoutedWord(c);
writeln(typeof(qoutedWord(c)).stringof," ", c);
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
char[] "test a"
const(char)[] "test b"
string "test c"
プロパティ関数
プロパティを使用すると、メンバー変数などのメンバー関数を使用できます。@propertyキーワードを使用します。プロパティは、要件に基づいて値を返す関連関数にリンクされています。プロパティの簡単な例を以下に示します。
import std.stdio;
struct Rectangle {
double width;
double height;
double area() const @property {
return width*height;
}
void area(double newArea) @property {
auto multiplier = newArea / area;
width *= multiplier;
writeln("Value set!");
}
}
void main() {
auto rectangle = Rectangle(20,10);
writeln("The area is ", rectangle.area);
rectangle.area(300);
writeln("Modified width is ", rectangle.width);
}
上記のコードをコンパイルして実行すると、次の結果が得られます。
The area is 200
Value set!
Modified width is 30