Thread overview
D'de Döngülerin Farkları Nedir?
Jun 15, 2022
dunecourser
Jun 15, 2022
dunecourser
Jun 15, 2022
dunecourser
Jun 15, 2022
Ali Çehreli
Jun 16, 2022
Salih Dincer
Jul 10, 2022
Salih Dincer
June 15, 2022
Bence başlığın isminde okuduğunuzdan daha ilginç bir konu bu.

D'nin üç ayrı döngüsü var: while, for ve foreach. Bunların her biri istenirse birbirinin yerine kullanılabilir, gelgelelim kullanıcının döngüyü ne kadar hassasiyetle kontrol etmek istediğine bağlı olarak tercihi değişecektir. Hassasiyete göre sıralarsak while > for > foreach olacağından şüphemiz yok, değil mi? Asıl değinmek istediğim de bu işte bu.

DMD inanılmaz hızlı bir derleyici. Hem de kullanıcının özensizsizliği yüzünden Allah bilir ne kadar optimizasyonla uğraştığı hâlde.

Aşağıdaki bu kodun çirkin bir kod olduğunu hepimiz biliyoruz.

---
T[] sıralıBirDiziOluştur(T)(size_t uzunluk)
// sıralıBirDiziOluştur!int(10) -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

foreach (eleman; sıralıBirDiziOluştur!int(10)){}
---

Bir sıranın üzerinde gezinmek için bir maliyetli yeni bir dizi oluşturduk. Belki de tek yapmak istediğimiz elamanları writeln aracılığıyla ekrana yazdırmak olacak. DMD derleme anında bu kodu fonksiyona girmeksizin foreach (eleman; [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) hâline getirecek kadar akıllı mı bilmiyorum. Ancak uğraştığı optimizasyonların bazılarının bunun gibi durumlar olduğu konusunda hemfikir olmalıyız.

Belki de aşağıda gördüğünüz kod için bunu aynen yapıyordur:

---
foreach (eleman; 1..11){}
// DMD: foreach (eleman; [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

if ("mor" in Renkler){}
// DMD: if ("mor" == ("sarı" || "kırmızı" || "mavi"))
---

O hâlde bu optimizasyonlarla daha az uğraşacak bir derleyici daha hızlı derleme süreleri demek. "DMD zaten dehşet derecede hızlı, bunlara ne gerek var?" diye sorarsanız, ne gerek var ben de bilmiyorum. :D

SORULAR:

---
size_t i; while (i < 10) { i+=1 ]; // ya da ...i < 10) continue i+=1;

for (size_t i; i < 10; i+=1) {}

foreach (e; 0..10) {}
---

1) Yukarıdaki döngülerden hangisi daha hızlıdır? (öhöm, godbolt.org'taki assembly çıktıları birbirinden farklı)

2) Sahi, while son derece yeterli; D'de yok ama bir shadowing özelliğimiz olsa for'u farksız simüle edebilirdi. Daha az yazmak ve okunaklılık dışında neden bir for'umuz var?

3) Hazır godbolt.org demişken arada kaynamasın: for'un ürettiği, ola ki while'inkiyle karşılaştırırsak çirkin bir assembly mi, zira bu bile derleme sürelerinde farklar ortaya çıkarıyor sanıyorum. (önemsemeyeceğimiz kadar küçük olsun olmasın)

4) Yukarıda döngüleri hassasiyetlerine göre sıraladık. döngüleri oluşturma mantığının maliyetine göre sıralarsak bu sıra foreach >= for > while olmalıdır, yanılıyor muyum?

Bu başlıktaki tartışmalar D'nin range'lerinin gücünü anlamak konusunda da yararlı olacaktır diye düşünüyorum. Umut Sarıkaya'nın bir karikatürünü range'lere uyarlacağım izninizle, birazcık hayal gücünüzü kullanmanız gerekebilir.

- Önder abi buyur gel range övelim abi...
- Sağol canım yeni övdüm... Başka zaman överiz...
- Abi range'lerin alan ve iterate'teki başarısı...
- Yavrum yeni övdüm diyorum başka zaman!

June 15, 2022
On Wednesday, 15 June 2022 at 16:34:22 UTC, dunecourser wrote:

> 1) Yukarıdaki döngülerden hangisi daha hızlıdır? (öhöm, godbolt.org'taki assembly çıktıları birbirinden farklı)

Düzeltme: for ve while'ın en temel kullanımları aynı çıktıyı üretiyor. Ben çoğu durum nazarında sordum.


June 15, 2022
On Wednesday, 15 June 2022 at 16:43:47 UTC, dunecourser wrote:
> On Wednesday, 15 June 2022 at 16:34:22 UTC, dunecourser wrote:
>
>> 1) Yukarıdaki döngülerden hangisi daha hızlıdır? (öhöm, godbolt.org'taki assembly çıktıları birbirinden farklı)
>
> Düzeltme: for ve while'ın en temel kullanımları aynı çıktıyı üretiyor. Ben çoğu durum nazarında sordum.

Bir düzeltme daha: aşağı yukarı aynı çıktıyı üretiyor... Bunu daha detaylandırmayacağım.
June 15, 2022
On 6/15/22 09:34, dunecourser wrote:

> while > for > foreach
> olacağından şüphemiz yok, değil mi?

Bence de öyle. Bir de "alt düzey" veya "üst düzey" olma konusu var. O açıdan da while en alt düzey kabul edilmeli. (Zaten foreach'in eninde sonunda while'a "lower" edildiği söylenir.)

Programcı olarak olabilen en üst düzeyi kullanmak istiyorum ama bunu yaparken performanstan ödün vermek de istemiyorum.

> DMD inanılmaz hızlı bir derleyici.

Hem de nasıl! :) Ama işin içine derleme zamanı olanakları girince işler çok yavaşlayabiliyor çünkü o olanakların derleyicide iyi gerçekleştirilmemiş olduklarını duyuyorum.

> Aşağıdaki bu kodun çirkin bir kod olduğunu hepimiz biliyoruz.

foreach diye mi yoksa gereksizce dizi oluşturuldu diye mi?

>
> ---
> T[] sıralıBirDiziOluştur(T)(size_t uzunluk)
> // sıralıBirDiziOluştur!int(10) -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>
> foreach (eleman; sıralıBirDiziOluştur!int(10)){}
> ---

> DMD derleme anında bu kodu
> fonksiyona girmeksizin foreach (eleman; [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
> hâline getirecek kadar akıllı mı bilmiyorum. Ancak uğraştığı
> optimizasyonların bazılarının bunun gibi durumlar olduğu konusunda
> hemfikir olmalıyız.

Ne demek istediğini anlıyorum ama dinamik dizi oluşturmayacağından eminim. 1..11'in masrafı, kendimizin for ile oluşturmuş olduğundan fazla değildir. (Olmamalı!)

> ---
> size_t i; while (i < 10) { i+=1 ]; // ya da ...i < 10) continue i+=1;
>
> for (size_t i; i < 10; i+=1) {}
>
> foreach (e; 0..10) {}
> ---
>
> 1) Yukarıdaki döngülerden hangisi daha hızlıdır? (öhöm, godbolt.org'taki
> assembly çıktıları birbirinden farklı)

Aynı olmalarını beklerim.

Ek olarak, eğer sınırın 10 olduğu biliniyorsa, aslında while'ın ve for'un fazladan bir denetimleri daha oluyor. O yüzden derleyici (veya programcı) şunun gibi bir döngüyü yeğleyebilir:

  size_t i;
  while (true) {
    // ...
    i++;
    if (i == 10) {
      break;
    }
  }

Koşulsuz döngüler, özellikle birden fazla sonlanma koşulu olduğunda çok yararlı oluyor.

> Daha az yazmak ve
> okunaklılık dışında neden bir for'umuz var?

Ayrıca tekrardan kaçınmak istiyoruz çünkü her tekrarda hata yapabiliriz. Zaten o yüzden üst düzeyi tercih ederiz.

> 4) Yukarıda döngüleri hassasiyetlerine göre sıraladık. döngüleri
> oluşturma mantığının maliyetine göre sıralarsak bu sıra foreach >= for >
> while olmalıdır, yanılıyor muyum?

> - Yavrum yeni övdüm diyorum başka zaman!

O zaman benim öncelikle düşündüğüm iota(10)'u hiç göstermeyelim. :)

Ali

June 16, 2022

On Wednesday, 15 June 2022 at 16:34:22 UTC, dunecourser wrote:

>

Bence başlığın isminde okuduğunuzdan daha ilginç bir konu bu.

D'nin üç ayrı döngüsü var: while, for ve foreach. Bunların her biri istenirse birbirinin yerine kullanılabilir, gelgelelim kullanıcının döngüyü ne kadar hassasiyetle kontrol etmek istediğine bağlı olarak tercihi değişecektir. Hassasiyete göre sıralarsak while > for > foreach olacağından şüphemiz yok, değil mi? Asıl değinmek istediğim de bu işte bu.

Teorik olarak tek döngü var ama Assembly'de bile dallanma komutları mikroişlemciye göre çok fazladır; sıralasak saymaya gücümüz yetmez! Ama en temele inme niyetimiz yok, öyle değil mi?

D'deki bir başka döngü label'lar. Örneğin:

Loop:
  // işlemler...
goto loop;

Belki de bu en basiti ve her dilde yoktur. Ayrıca hemen hemen her dilde olan switch case ile de döngü yapmanız mümkün hem de çok işlevsel. Tıpkı `for()' ile yaptığımız çift değişkenli döngülerin de ötesinde!

Bence foreach() hepsinden ayrılır ve onu ayrı bir kefeye koymalıyız. Sebepleri aşikar ama çok isterseniz örneklerle üzerinde tartışabiliriz?

while() ise candır, canandır! Tam anlamıyla anlamak için oturup onlarca örnek yazmalısınız. Basittir ama do ile kullanıldığında (pek sık kullanılmaz) başka bir kişiliğe bürünebilir. Yanlış hatırlamıyorsam Pascal'da da bu 2. kişiliğin karşılığı "repeat until()" olması lazım. C ve türevleri bunu çok iyi geliştirmiş.

Son olarak işlevleri birbirleriyle çağırmak da döngü yapmak için yeterlidir ama bellek yeter mi tartışılır. Bir recursive function ne kadarmümkünse o da mümkündür herhalde 😀

On Wednesday, 15 June 2022 at 16:34:22 UTC, dunecourser wrote:

>

DMD inanılmaz hızlı bir derleyici. Hem de kullanıcının özensizsizliği yüzünden Allah bilir ne kadar optimizasyonla uğraştığı hâlde.

Aslında LDC'ye göre çok yavaş ama sahip olduğu yetenekler çok fazla. Aralıkları hesaba kattığımızda foreach() de çok güçlüdür. Ona benzeyen şu Template olanağı da konuşmalı:

  auto result = range.each!(a => ... );

Son görüntülü sohbetimizde bu konuya değindik hatta Ali hoca kaynak kodlarına da baktı.

Sevgiler, saygılar...

July 10, 2022

On Thursday, 16 June 2022 at 05:23:23 UTC, Salih Dincer wrote:
herhalde 😀

>

On Wednesday, 15 June 2022 at 16:34:22 UTC, dunecourser wrote:

>

DMD inanılmaz hızlı bir derleyici. Hem de kullanıcının özensizsizliği yüzünden Allah bilir ne kadar optimizasyonla uğraştığı hâlde.

Aslında LDC'ye göre çok yavaş ama sahip olduğu yetenekler çok fazla. Aralıkları hesaba kattığımızda foreach() de çok güçlüdür. Ona benzeyen şu Template olanağı da konuşmalı:

  auto result = range.each!(a => ... );

Bağlantısını vereceğim başlıkta D döngülerini test etmeye çalıştım. Meğer LDC kısacık döngüler için gereksiz etiketler kullanıyormuş!

https://forum.dlang.org/post/obnmtbjpqfnialydfpjf@forum.dlang.org

Dip Not: Bu arada bir düzeltmeyi buradan yapayım. Binlerce hatta bini aşkın dediğim kodlar std.stdio'yu iptal etmeden yaptığım incelemenin neticesiymiş.