foreach diziler üzerinde sayaçlı ilerlemeyi destekler. İki döngü değişkeni tanımlandığında birincisi sayaçtır, ikincisi de eleman:
foreach (i, eleman; [ 10, 20, 30 ]) {
writeln(i, ": ", eleman);
}
Çıktısı:
'0: 10
1: 20
2: 30
'
Ne yazık ki bu kendi türlerimiz için otomatik değildir. Kendimiz sayaçlı döngü istediğimizde türümüz için sayaç da alan bir opApply() tanımlamamız gerekir. Şurada "Döngü sayacı" başlığı altında var:
http://ddili.org/ders/d/foreach_opapply.html
O yöntem hem daha zordur hem de foreach desteği aralık işlevleri ile zaten verildiğinde gereksiz kabul edilmelidir. Ne yazık ki D bu konuda bir destek getirmiyor ama std.range modülünde yeterli olanak varmış.
Şöyle bir aralığımız olsun:
import std.stdio;
struct FibonacciSerisi
{
int baştaki = 0;
int sonraki = 1;
enum empty = false;
@property int front() const
{
return baştaki;
}
void popFront()
{
int ikiSonraki = baştaki + sonraki;
baştaki = sonraki;
sonraki = ikiSonraki;
}
}
void main()
{
auto aralık = take(FibonacciSerisi(), 10);
foreach (eleman; aralık) {
writeln(eleman);
}
}
Sayaç gerekmediği zaman güzelce çalışıyor:
'0
1
1
2
3
5
8
13
21
34
'
Ama işte foreach sayacı eklediğimizde çalışmıyor:
foreach (i, eleman; aralık) { // <-- HATA
writeln(i, ": ", eleman);
}
Derleme hatası türlerin çıkarsanamadıklarını belirtiyor (çünkü aralığımızın opApply()'ı yok. (Zaten dikkat ederseniz aralık bizim aralığımız değil, take()'in döndürdüğü aralık.)):
'Error: cannot infer argument types'
Yeni öğrendiğim yöntem şu:
import std.range;
// ...
foreach (i, eleman; zip(sequence!"n"(), aralık)) {
writeln(i, ": ", eleman);
}
Şimdi çalışıyor:
'0: 0
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
'
sequence bir seri eleman üretmek için kullanılıyor. Şablon parametresinde 'n' ile ifade edilen şey sequence'ın otomatik olarak arttırdığı bir değer. O değer, yalnızca 'n' yazınca 0, 1, 2, ... diye gidiyor. (sequence'a işlev parametreleri de verilebiliyormuş; o parametreler de şablon parametresi içinde a[0], a[1], vs. olarak yazılıyorlarmış ama denemedim.)
zip ise kendisine verilen bir veya daha fazla aralığı aynı hızda adım adım ilerletiyor. Yani sequence'ı bir ilerletirken aralık'ı da bir ilerletiyor. Sonuç olarak da kendisine verilen aralık adedi kadar elemanı bulunan bir çokuzlu döndürüyor.
O çokuzlunun elemanlarının foreach döngü değişkenlerine karşılık gelmeleri ve döngü içinde 'i' ve 'eleman' olarak kullanılabilmelerine de çok şaşırıyorum. :)
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]