Yeni yaptığım faydalı test sonuçları şöyle:
-
D’de function literal olarak anılan delegate ve function türünde olmak üzere 2 lambda işlev vardır. Bunların farklı yazım türlerinden dolayı kısa/uzun, tek satır veya isimsiz/anonim kullanım şekilleri olsa da çoğu birbirinin hemen hemen aynısıdır. Derleyici kontrolünde
auto
ile kurulması tavsiye edilir. -
Delegate (temsilci) olarak tanımlanan uygulamanın diğerine göre bir avantajı vardır. O da içinde bulunduğu kapsamın dışında tanımlı nesnelere erişebilmesidir. Ancak function öyle değidir, global alanda tanımlananlar hariç, bir yapı/sınıf içinde bile
this
’e erişemez. Her ikisi de yerel değişkenlerine doğal olarak erişir. -
Sıradan bir işlev gibi tek başına çağrıldığında mutlaka sonunda 2. bir parantez aç/kapa olmalıdır. Ama hem UFCS ile çalışır, hem de ilk parametre soluna yazılsa ve () işareti unutulsa bile çağrıldığı yere by-value olarak dönüş sağlar. Eğer parametre almıyorsa isimsiz olanı saymazsak baştaki () işaretini kullanmayabilirsiniz. Örneğin:
auto logYaz = {
auto logger = new LOGLAYICIM(LogLevel.info);
logger.log("Kurulum tamam, hata yok.");
}
-
Dilerseniz, derleme zamanı değerlere ihtiyaç duyan uygulamalar için (örn. bir yapı içine işlev enjekte etmekte)
alias
kullanabilirsiniz Pratikte faydası olmasa daconst
ile de kurabilirsiniz ama sadece aldığı parametrelerde kullandığınızda etkisini görebilirsiniz. Çünkü kendi içinde (eğer erişebiliyorsa) kapsam dışındakileri değiştirmeye devam edecektir. O yüzden delegate türünü kullanırken dikkatli olmalısınız, affetmez! -
Dilerseniz de iki aşamalı, sanki virtual function tanımlar gibi (sınıflardaki abstract konusuna bakınız) hiçbir şeye eşitlemeden daha sonra neyi tanımladıysanız ona uygun bir işlev bağlanabilir. (-bknz. örnekteki global delegate/function tanımlaması, farketmez
main()
içinde de olabilir)
Bu 5 madde dışında başka sonuçlar da çıkarabilir ya da eksik ifadeler olabilir. Ama lütfen, örnek kod sonundaki bonus'lara da bakıptest()
'den başlayarak deneyiniz.
Aslında konu,şurada örnekleriyle anlatılıyor. Ayrıca Ali Çehreli'nin kitabındaki ilgili bölümde daha fazla bilgi ve örnek mevcut. Ama hızlıca denemek isterseniz elde ettiğim sonuçları aşağıdaki örneklerde görebilirsiniz:
import std.stdio;
void test()
{
string str;
// ^-- bu noktada str = null
(){
str = "Merhaba D";
}();
// ^-- tam bu noktada str değişir
auto anonim = {
str = "Merhaba C";
return 0;
};
// Ama bu çağrılmayı bekler...
str.writeln; // "Merhaba D"
anonim(); /* int delegate() türünde bir işlev,
gereksiz yere 0 değerini döndürür */
str.writeln; // "Merhaba C"
anonim = () => 1;
anonim().writeln; /* Şimdi döndürdüğü kullanılır
ama dileseydik temsilci kullanmazdık: */
auto func = () => 2;
typeid(func).writeln; // ÇIKTISI:
// int function() pure nothrow @nogc @safe*
int i = 3;
// func = () => i;
} /* Bu değer --^
döndürülemeyeceği için kod derlenmez! */
Çünkü function türünde kurmuştuk. Eğer delegate olsaydı main()
içinde temsil edilebilirdi. Ayrıca dikkat: @safe
yanındaki asterix (*) işaretine bakılırsa by-value değilmiş! Sizce neden delegate'de işaretçi olduğu belirtilmemiş olabilir? Çünkü zaten temsilci nesne olduğu için mi?
int eight = 8;
int dokuz() { return 9; }
int sekiz() { return eight; }
int delegate() del;
int function() fun;
void main()
{
test();
auto dokuz = 9;
// del = () => 8;/* bu satır yerel değişken döndürür
del = ()
{
return dokuz;
}; /*
Bu temsilci (delegate) işlev yerel olmayan değer
de döndürebilir */
// fun = () => dokuz;/* bu satır derlenöz!
fun = ()
{
return 8; // eight; <-- bunu da dene, lütfen!
}; /*
Bu anonim (function) işlevin derlenmediğinde,
Error: __lambda2 cannot access
frame of function D main
hatası verir çünkü bulunduğu kapsamın yerel değişken döndürür */
writeln("- Lambda işlevler: () ile kullanıma dikkat!");
del().writeln(", ", fun());
"\n".writeln("- Normal işlevler:");
dokuz.writeln(", ", sekiz);
}
6. numara (bonus):
Eğer denediyseniz fun()
eight değişkenine erişebiliyor çünkü global alanda tanımlanmış. Burada delegate/function farklı bellek alanlarında bulunduğu sonucu çıkarılabilir. Bilemiyorum belki de izinler ile ilgili bir durumdur.
Ayrıca farkettiyseniz dokuz()
işlevi ile main()
içindeki aynı isimde değişken karışmıyor. Çünkü farklı kapsamlarda (biri global'de) ve hata da vermiyor. Derleyiciye yardım etmek istersek sonunda () işaretini koyabiliriz. Bir benzerini şu örnekte de uygulabilirsiniz:
int delegate(int) karesi;
void main()
{
karesi = (int a) => a * a;
int karesi = 5.karesi;
assert(karesi == 25);
}
Başarılar...