D Programlama - Fonksiyonlar
Bu bölüm, D programlamada kullanılan fonksiyonları açıklamaktadır.
D'de Fonksiyon Tanımı
Temel bir işlev tanımı, bir işlev başlığı ve bir işlev gövdesinden oluşur.
Sözdizimi
return_type function_name( parameter list ) {
body of the function
}
İşte bir işlevin tüm bölümleri -
Return Type- Bir işlev bir değer döndürebilir. return_typeişlevin döndürdüğü değerin veri türüdür. Bazı işlevler, bir değer döndürmeden istenen işlemleri gerçekleştirir. Bu durumda, dönüş_türü anahtar kelimedirvoid.
Function Name- Bu, işlevin gerçek adıdır. İşlev adı ve parametre listesi birlikte işlev imzasını oluşturur.
Parameters- Parametre, yer tutucu gibidir. Bir işlev çağrıldığında, parametreye bir değer iletirsiniz. Bu değere gerçek parametre veya bağımsız değişken adı verilir. Parametre listesi, bir fonksiyonun parametrelerinin türü, sırası ve sayısı ile ilgilidir. Parametreler isteğe bağlıdır; yani, bir işlev hiçbir parametre içermeyebilir.
Function Body - İşlev gövdesi, işlevin ne yaptığını tanımlayan bir dizi deyim içerir.
Bir Fonksiyon Çağırma
Bir işlevi aşağıdaki şekilde çağırabilirsiniz -
function_name(parameter_values)
D'deki Fonksiyon Türleri
D programlama çok çeşitli işlevleri destekler ve aşağıda listelenmiştir.
- Saf İşlevler
- Nothrow İşlevleri
- Ref İşlevleri
- Otomatik İşlevler
- Değişken Fonksiyonlar
- Inout Fonksiyonları
- Özellik İşlevleri
Çeşitli işlevler aşağıda açıklanmıştır.
Saf İşlevler
Saf işlevler, bağımsız değişkenleri aracılığıyla küresel veya statik, değiştirilebilir duruma erişemeyen işlevlerdir. Bu, saf bir işlevin kendisine aktarılmayan hiçbir şeyi değiştirmesinin garantili olduğu gerçeğine dayalı optimizasyonları etkinleştirebilir ve derleyicinin saf bir işlevin argümanlarını değiştiremeyeceğini garanti edebildiği durumlarda, tam, işlevsel saflığı etkinleştirebilir, işlevin aynı bağımsız değişkenler için her zaman aynı sonucu döndüreceğinin garantisidir).
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));
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Value returned from pure function : 30
Nothrow İşlevleri
Nothrow işlevleri, sınıf Exception'dan türetilen herhangi bir istisna atmaz. Nothrow işlevleri, atma işlevleriyle birlikte değişkendir.
Nothrow, bir işlevin herhangi bir istisna yaymayacağını garanti eder.
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));
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
adding
Added value is 30
Ref İşlevleri
Ref fonksiyonları, fonksiyonların referans olarak dönmesine izin verir. Bu, ref fonksiyon parametrelerine benzer.
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);
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
a: 1, b: 12
Otomatik İşlevler
Otomatik işlevler her türden değer döndürebilir. Hangi türün iade edileceğine dair herhangi bir kısıtlama yoktur. Otomatik tür işlevi için basit bir örnek aşağıda verilmiştir.
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));
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
add(a,b) = 3.5
Değişken Fonksiyonlar
Variadiac fonksiyonlar, bir fonksiyon için parametre sayısının çalışma zamanında belirlendiği fonksiyonlardır. C'de en az bir parametreye sahip olmanın bir sınırlaması vardır. Ancak D programlamada böyle bir sınırlama yoktur. Aşağıda basit bir örnek gösterilmektedir.
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);
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
int 2
long 3
double 4.5
Inout Fonksiyonları
Giriş, işlevlerin hem parametre hem de dönüş türleri için kullanılabilir. Değişken, sabit ve değişmez için bir şablon gibidir. Değişebilirlik niteliği parametreden çıkarılır. Demek ki, inout, çıkarılan değişkenlik özniteliğini dönüş türüne aktarır. Değişkenliğin nasıl değiştiğini gösteren basit bir örnek aşağıda gösterilmiştir.
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);
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
char[] "test a"
const(char)[] "test b"
string "test c"
Özellik İşlevleri
Özellikler, üye değişkenler gibi üye işlevlerinin kullanılmasına izin verir. @Property anahtar sözcüğünü kullanır. Özellikler, gereksinime göre değerler döndüren ilgili işlevle bağlantılıdır. Mülkiyet için basit bir örnek aşağıda gösterilmiştir.
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);
}
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The area is 200
Value set!
Modified width is 30