Thread overview
Aralık Durumunu Yedekleme
Aug 28, 2022
Salih Dincer
Aug 28, 2022
Salih Dincer
Aug 29, 2022
Ali Çehreli
Aug 29, 2022
Ali Çehreli
Aug 29, 2022
Salih Dincer
Aug 29, 2022
Ali Çehreli
Aug 30, 2022
Cos00kun
Aug 30, 2022
Ali Çehreli
Aug 31, 2022
Cos00kun
August 28, 2022

Merhaba,

Aşağıdaki gibi, BüyükHarf(E)'leri aralık olarak döndüren bir yapımız olsun. Bunun sınırlarını bir enumerator(enum, E) ile pratik şekilde ve derleme zamanında kurulurken bildirebiliriz; örnekteki ARALIK gibi...

enum ARALIK { başı = 'A', sonu = 'F' }
struct BüyükHarf(E)
{
  invariant(E.başı >= 65, "\n  A harfinden az olamaz");
  invariant(E.sonu <= 90, "\n  Z harfinden fazla olamaz");

  //static
  private char im = E.başı;

  @("InputRange İşlevleri:") //<-- kabul, UDA'in gereksiz kullanımı :)
  {
    bool empty() { return im > E.sonu; }
    char front() { return im; }
    void popFront()   { ++im; }
  }

  auto opCall(char c)
  in(c >= 65, "\n  A harfinden az olamaz")
  {
    auto öncesi = im;
    //scope(exit) im = öncesi;
    im = c;
    return this;
  }
}

import std.stdio;
void main()
{
  BüyükHarf!ARALIK harfler;

  harfler.writeln; // "ABCDEF"

  foreach(harf; harfler('C'))
  {// opCall() özelliği--^
    harf.write(" ");
  }
  writeln; // "C D E F "

  harfler.writeln; // "CDEF" ops!!!
}
/* opCall()'da scope(exit) varsa, aldığım çıktı:

dmd -w -run "struct.d" (/home/salihdb/Belgeler/YeniD/Forumdan Sorular dizininde)
ABCDEF
C D E F
ABCDEF
Derleme başarılı.
*/

Elbette bu kadar tantanaya gerek yoktu. Maksadımız öğrenmek, yoksa aşağıdaki gibi (tabi F'yi dahil etmeyecekti!) tek satırla aralık oluşturabilirdik ve kodumuzun herhangi bir yerinde kullanabilirdik:

  import std.range : iota;
  auto harfAralık = ARALIK.başı.iota!char(ARALIK.sonu);

Ama ekstralar kullanmadan bir şeyi yapamazdık: Aralığın başladığı nokta private değişken olduğuna göre, bunu değiştirip oradan itibaren gezinmesi kolay olmazdı. Tamam, aşağıdaki gibi filitrelemek elbette mümkün ama arkaplanda bir "skipping with iteration" olsa gerek:

  import std.algorithm : filter;
  harfAralık.filter!(c => c >= 'C').writeln; // "CDE"

Öte taraftan, Ali hocanın InclusiveRange() gibi aralık oluşturan bir yapıya ihtiyacımız var. Çünkü iota() bizim için pratik değil; hele bu örnekte hiç! Eğer F'yi de dahil etmek isteseydiniz ve ARALIK'ı kullanarak iota!char(başı, sonu + 1) işe yaramayacaktı! Özellikle char'ı belirtmemize rağmen şu çıktıyı alacaktık:

>

[67, 68, 69, 70]

Çünkü otomatik olarak int'e bir tür dönüşümü gerçekleşti, bence saçma! Örneğimize geri dönersek...

Klasik üçlü InputRange işlevleriyle pekala aralıkta gezinebiliriz. Özellikle foreach() kullanırsak aralığın yedeğini alacağı için tükenmiş olması dıştaki satırları etkilemeyecekti; nedense opCall() ile istisna!

  auto opCall(char c) {
    auto öncesi = im;
    scope(exit) im = öncesi;
    im = c;
    return this;
  }

Yukarda çalışma zamanı[1] sözleşme öğesini kaldırıp, scope(exit)'ı etkinleştirdim. Bu kapsamdan çıkıldığında im değişkenini tekrar öncesine dönmesini sağlar. Yani yan etkiyi düzeltmek için ekstra özelliğe ihtiyacımız vardı ve bunu bize D sağladı.

Sorulara gelince; bu yan etki niye var ve daha temiz/güvenli bir aralık üreten yapı kodlanabilir miydi? Bunu soruyorum çünkü foreach()'in aralığı tüketmeden önce yedeğini aldığını biliyorum. Elbette kapsam (main) dışında kolaylık işlevleri[2] yapılabilirdi. Ama yedeğini aldığım nesnenin opCall'ını çağırdığımı ve bunun static char im diye bir değişkeni olmadığını düşünüyorum!

  1. Kabul, bu derleme zamanında hata vermesi sağlanabilirdi.
  2. Kolaylık işlevlerini denemedim çünkü çok basitti ama yedeğini aldığımda opCall içinde ekstra bir yedekleme ihtiyacı duymadım.

Teşekkürler...

Salih Dinçer

August 28, 2022

10 dakka sonra kafaya dank etti :)

Meğer henüz döngü başlatmadan opCall() içindeki olayı, aşağıdaki gibi bir satır öncesinde yapıyor ve değişmiş halini foreach'e yönlendiriyorsunuz. Yani döngü başlamadan önce zaten değişiyor!

  harfler.im = 'C';
  foreach(harf; harfler)
  {
    harf.write(" ");
  }

Hepsi bu aslında!

August 29, 2022
On 8/28/22 03:42, Salih Dincer wrote:

>    invariant(E.başı >= 65, "\n  A harfinden az olamaz");

invariant'ın da "sözleşme ifadesi" (expression contracts) yazımını kullanabildiğini bilmiyordum. Şurada in ve out için göstermişim:


http://ddili.org/ders/d/sozlesmeli.html#ix_sozlesmeli.s%C3%B6zle%C5%9Fme%20ifadeleri

Ama invariant için eksik kalmış:

  http://ddili.org/ders/d/invariant.html#ix_invariant.invariant

>    auto opCall(char c)
>    in(c >= 65, "\n  A harfinden az olamaz")
>    {
>      auto öncesi = im;
>      //scope(exit) im = öncesi;
>      im = c;
>      return this;
>    }

Tabii ki bunların deneme kodları olduğunu biliyorum ama opCall yerine opAssign kullanılsa daha iyi mi anlaşılır? Ama yine de aralığın başı mı değişir sonu mu? Açık değil.

>    foreach(harf; harfler('C'))
>    {// opCall() özelliği--^

Örneğin, o kullanım hiç açıklayıcı değil.

> Öte taraftan, Ali hocanın `InclusiveRange()` gibi aralık oluşturan bir
> yapıya

O kod üzerinde birlikte çalışmıştık ve ben InclusiveRange'i de pek kullanışlı bulmuyorum. Galiba bir kaç soru işaretini de cevapsız bırakmıştık.

Ayrıca çok fazla becerikli olmaya çalışıyordu. Örneğin, bazı D'ci arkadaşlarımız Phobos'un iota'sının bile gereksizce fazla becerikli olmaya çalıştığını düşünüyorlar:

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

(O tartışma da benim bir DConf sunumuma bağlı... :) )

> `foreach()` kullanırsak aralığın yedeğini alacağı için
> tükenmiş olması dıştaki satırları etkilemeyecekti; nedense `opCall()`
> ile istisna!

Ben de geçende bir yapımın foreach ile kullanılabilmesi için opCall işlevini tanımlaması gerektiğini farkettim. Kopyalanması önlenmiş yapılar foreach ile kullanılamıyor:

struct S {
  @disable this(this);
  // ...
}

Ali

August 29, 2022
On 8/29/22 10:41, Ali Çehreli wrote:

> Ben de geçende bir yapımın foreach ile kullanılabilmesi için opCall
> işlevini tanımlaması gerektiğini farkettim.

opApply demek istemiştim, opCall değil.

Ali

August 29, 2022

On Monday, 29 August 2022 at 17:41:44 UTC, Ali Çehreli wrote:

>

...
Ayrıca çok fazla becerikli olmaya çalışıyordu. Örneğin, bazı D'ci arkadaşlarımız Phobos'un iota'sının bile gereksizce fazla becerikli olmaya çalıştığını düşünüyorlar

Nesnelere birden fazla yetenek bağlama konusunda ben de çok kararsızım. Bazen bir yapıyı olabilecek bütün yüklemeler ile donatmak hoşuma giderken ihtiyaç olmayacaksa ne gerek var diyor insan. 😀

Elimizde, her işleve otomatik bir sayaç ekleme özelliği olsa ve yazdığımız programlarda, kütüphanemizdeki hangilerine daha sık eriştiğimizi sıralayan bu olanağı kulanabilseydik, harcadığımız değersiz saatleri görebilirdik! (Vuuuvw, bu cümleyi/paragrafı İngilizce kurup da derdimi anlatamazdım sanırım 😀)

>

Ben de geçende bir yapımın foreach ile kullanılabilmesi için opApply
işlevini tanımlaması gerektiğini farkettim. Kopyalanması
önlenmiş yapılar foreach ile kullanılamıyor:

struct S {
 @disable this(this);
 // ...
}

Bunu bilmiyordum hocam, teşekkürler.

Yapılara öyle alıştım ki anlatamam ve onlarsız yapamam! Hele ki ben GWBASIC=>QBASIC'den gelmiş, Commodore64'da kod yazmış, sonra PC'de Pascal=>Delphi derken Pascal'a benzeyen ondan bir şeyler alan ve ismimin baş harfi olan D'de karar kıldım ya hiç pişman değilim. 30 sene öncesini bırakın 10 sene öncesi ile bile karşılaştırsam büyük farklar ve kolaylıklar var. Neredeyse sınıfları hiç kullanmıyorum hele, şaşırtıcı!

Sevgiler, saygılar...

August 29, 2022
On 8/29/22 13:05, Salih Dincer wrote:

> Nesnelere birden fazla yetenek bağlama konusu

...çok yanlış. :p

> Elimizde, her işleve otomatik bir sayaç ekleme

Onları elle eklemek hem zor oluyor hem de pek bilgi vermiyor. dmd'nin -profile seçeneği gibi seçenekler kullanılabilir. Ya da şunlar yeterli oluyor:

  https://dlang.org/phobos/std_datetime_stopwatch.html

> Neredeyse sınıfları hiç kullanmıyorum

C++ altında o kadar sene "herşey bir sınıftır" saçmalığını çektikten sonra büyüdükçe sınıfların yalnızca çalışma zamanı çokşekilliği (runtime polymorphism) için olduğunda karar kıldım. (Benim kararımla ilgisi yok; zaten öyle... :) )

Çalışma zamanında tür değişikliği de çok nadiren gerektiğinden sınıflar çok az kullanılıyor.

Kaldı ki, sınıfların yaptığı her şey biraz el emeğiyle zaten C'de bile yapılabiliyordu.

Evet, hemen hemen her zaman yapılar...

Ali

August 30, 2022
Ne oluyor burada!! bir zamanlar mucize diye adlandırdığımız modern çağın nimeti sınıflarıda mı geride bırakıyoruz yavaş yavaş :)

August 30, 2022
On 8/30/22 13:16, Cos00kun wrote:
> Ne oluyor burada!! bir zamanlar mucize diye adlandırdığımız modern çağın
> nimeti sınıflarıda mı geride bırakıyoruz yavaş yavaş :)

Sınıf bazı yerlerde çok kullanışlıdır. Ama genel programlamada hele D programlamada çok az karşılaşılıyor. Örneğin, DConf 2019 konuşmamda o zamanki kodlarımda 95 struct, 2 sınıf, 1 interface bulunduğunu söylemişim.

Ali

August 31, 2022
On Tuesday, 30 August 2022 at 20:23:22 UTC, Ali Çehreli wrote:
> Sınıf bazı yerlerde çok kullanışlıdır. Ama genel programlamada hele D programlamada çok az karşılaşılıyor. Örneğin, DConf 2019 konuşmamda o zamanki kodlarımda 95 struct, 2 sınıf, 1 interface bulunduğunu söylemişim.
>
> Ali

Umarım sebeplerini bende daha iyi anlayacağım biraz daha ileri zamanlarda.