static foreach
Derleme zamanı foreach olanağını daha önce Çokuzlular bölümünde görmüştük. O olanak, döngünün derleme zamanında işletilmesini ve kod olarak açılmasını sağlar. Örnek olarak bir çokuzlu üzerinde işletilen aşağıdaki döngüye bakalım:
auto t = tuple(42, "merhaba", 1.5); foreach (i, üye; t) { writefln("%s: %s", i, üye); }
Derleyici döngüyü aşağıdaki eşdeğeri olarak açar:
{
enum size_t i = 0;
int üye = t[i];
writefln("%s: %s", i, üye);
}
{
enum size_t i = 1;
string üye = t[i];
writefln("%s: %s", i, üye);
}
{
enum size_t i = 2;
double üye = t[i];
writefln("%s: %s", i, üye);
}
Çok güçlü bir olanak olmasına karşılık, bu olanak her durumda kullanışlı olmayabilir:
- Döngünün her açılımı farklı bir kapsam (ve isim alanı) tanımlar. Bu sayede, yukarıdaki koddaki
iveüyegibi değişkenler tanım tekrarı hatalarına neden olmadan kullanılabilirler. Bu bazı durumlarda yararlı olsa da, belirli bir döngü adımında açılan bir kodun başka bir döngü adımında açılan kod tarafından erişilmesini olanaksızlaştırır. - Derleme zamanı
foreacholanağı yalnızca çokuzlularla kullanılabilir (AliasSeqolarak erişilebilen şablon parameterleri dahil). Örneğin, aşağıdaki dizi sabit değeri derleme zamanında bilindiği halde,foreachdöngüsünün doğası gereği kod çalışma zamanında işletilir (bazı durumlarda istenen de tam olarak budur):
void main() { enum dizi = [1, 2]; // Derleme zamanında açılmaz, çalışma zamanında işletilir foreach (i; dizi) { // ... } }
- Normal
foreachgibi, derleme zamanıforeachdöngüsü de yalnızca işlev içlerinde kullanılabilir. Örneğin, modül düzeyinde veya kullanıcı türlerinin içlerinde kullanılamaz.
import std.meta; // Modül düzeyinde işlev yüklemeleri tanımlamaya çalışılıyor: foreach (T; AliasSeq!(int, double)) { // ← derleme HATASI T ikiKatı(T sayı) { return sayı * 2; } } void main() { }
Error: declaration expected, not foreach
breakvecontinuedeyimlerinin derleme zamanıforeach'inin kendisi ile mi yoksa açılan kodun parçası mı oldukları açık olmayabilir.
static foreach bu konularda daha fazla seçim sağlayan daha güçlü bir olanaktır:
- Derleme zamanında işletilebilen her çeşit aralıkla kullanılabilir (
1..10gibi sayı aralıkları dahil). Örneğin, Aralıklar bölümünde gördüğümüzFibonacciSerisiaralığı ve bir sayının çift olup olmadığını belirleyen bir işlev olduğunu varsayarak:
static foreach (n; FibonacciSerisi().take(10).filter!çift_mi) {
writeln(n);
}
Yukarıdaki döngü aşağıdaki eşdeğeri olarak açılır:
writeln(0);
writeln(2);
writeln(8);
writeln(34);
- Modül düzeyinde kullanılabilir
- Döngünün her adımı için farklı kapsam getirmez. Örneğin, aşağıdaki kod bir işlevin iki yüklemesini modül düzeyinde tanımlamaktadır:
import std.meta; static foreach (T; AliasSeq!(int, double)) { T ikiKatı(T sayı) { return sayı * 2; } } void main() { }
Yukarıdaki döngü aşağıdaki eşdeğeri olarak açılır:
int ikiKatı(int sayı) { return sayı * 2; } double ikiKatı(double sayı) { return sayı * 2; }
static foreachdöngüleri içindekibreakvecontinuedeyimlerinde etiket belirtilmesi şarttır. Örneğin, birswitchdeyimi içinecasebölümleri ekleyen aşağıdaki döngüde, açılmakta olan kodun parçası olanbreak, ilgili olduğuswitch'i bir etiketle bildirmektedir:
import std.stdio; void main(string[] parametreler) { switchDeyimi: switch (parametreler.length) { static foreach (i; 1..3) { case i: writeln(i); break switchDeyimi; } default: writeln("varsayılan davranış"); break; } }
Yukarıdaki döngü açıldığında bütün switch deyimi aşağıdakinin eşdeğeridir:
switch (parametreler.length) { case 1: writeln(1); break; case 2: writeln(2); break; default: writeln("varsayılan davranış"); break; }
Kitaplar
Forum
Tanıtım
İletişim
Hakları