Thread overview
Karamelize Soğan, Tereyağlı ve Rokforlu 200 gr. Hamburger
August 17

Hayır yanlış gelmediniz...

Burası bilgisayar kodlarının konuşulduğu, kodlarımızı paylaştığımız bir yer. Ama başlıktaki yemeğin, hiçbir diyette olmaması gerektiğinde hemfikiriz :)

Walter, bu ay başında yapılan Dconf'22 konuşmasında şuna benzer tarifi (ah pardon, kodu) vermişti:

static struct BoolEnum(E)
{
  private ubyte flags;

  private template Impl(ubyte mask)
  {
    bool Impl(bool v)
    {
      v ? (flags |= mask) : (flags &= ~mask); // Deprecation'a girmiş :)
      return v;
    }

    bool Impl() const scope
    {
      return !!(flags & mask);
    }
  }

  static foreach(mem; __traits(allMembers, E))
  {
    mixin("alias "~mem~" = Impl!(1 << E."~mem~");");
  }

  auto getFlags()
  {
    return flags;
  }

  void setAll()
  {
    this.flags = ubyte.max;
  }
}

Aslında aç programcımızı gereksiz ayrıntılarla boğmak istemiyorum. Sadece ye ve git ama kodu bu hale getirenlere haksızlık yapmayalım. Şurada, yukarıdaki yapı biraz geliştirildi ben ise kendime uyarladım ve 2 üye işlev ekledim.

Şimdi yapının işbirliği içinde çalıştığı bir enum yazalım (örn. Haftanın Günleri) ve bir de takma isim:

enum Günler {
  Cumartesi, Pazar, Pazartesi,
  Salı, Çarşamba, Perşembe, Cuma
}

alias bEnum8 = BoolEnum!Günler;

Hamburgerimiz neredeyse hazır! Bunun için AA (Associative Arrays) ekmeğini alıp keskin bir bıçak ile iki eşit parçaya böleceğiz. Sonra lezzetli malzemelerimizi sıcak sıcak, servise hazır bir şekilde yerleştireceğiz:

void main()
{
  bEnum8[string] xDiyet = [
    "Çorba" : bEnum8(),
    "Brokoli" : bEnum8(),
    "Kabak" : bEnum8(),
    "Yoğurt" : bEnum8()
  ];

  xDiyet["Brokoli"].Pazar = true; // Bu Karamelize Soğan
  xDiyet["Yoğurt"].setAll(); // Bu da Rokfor Peynirli Sos

  auto sorgu1 = "Yoğurt";

  writef("Diyette %s var mı? ", sorgu1);
  if(sorgu1 in xDiyet) "Var.".writeln;
  else "Yok!".writeln;

  write("Peki her gün mü? ");
  if(xDiyet[sorgu1].tümHaftaTüket) "Evet.".writeln;
  else "Hayır!".writeln;
}

N'oluya lan, dediğinizi duyar gibiyim. Çok güzel şeyler oluyor, merak ederseniz yazarım yine. Ama yazmadan denemeler yapın lütfen.

Dip Not: Bir de alakasız bir soru. Deprecation uyarı veren bir satır var. Bunu nasıl düzeltiriz?

Sevgiler, saygılar...

August 17

On Wednesday, 17 August 2022 at 17:25:33 UTC, Salih Dincer wrote:

import std.stdio;

bool tümHaftaTüket(bEnum8 yemek) {
  if(yemek.getFlags > 0) {
    if(yemek.getFlags == ubyte.max)
      return true;
  }
  return false;
}

Yukardakileri unutmuşum. Şu sonucu almak için main() dışında dursunlar:

>

Diyette Yoğurt var mı? Var.
Peki her gün mü? Evet.

Dip Not: Bu arada başlığın ismi "AA ve Enum'lu Diyet Listesi" ama aç olduğumdan mı bilmiyorum bu örnek bana 200 gr. hamburger gibi geliyor :)

Başarılar...

August 17
On 8/17/22 10:25, Salih Dincer wrote:

>    xDiyet["Brokoli"].Pazar = true; // Bu Karamelize Soğan

Hep kafamızı karıştırmaya çalışıyorsun. Bence brokoli, karamelize soğan değildir. ;)

> **Dip Not:** Bir de alakasız bir soru. Deprecation uyarı veren bir satır
> var. Bunu nasıl düzeltiriz?

tümHaftaTüket() ile ilgili olmalı. Ben kodları derleyebilmek için o satırı çıkarttım ve uyarı almadım (dmd 2.100.0).

Ali

August 17
On 8/17/22 10:30, Salih Dincer wrote:

> bool tümHaftaTüket(bEnum8 yemek) {
>    if(yemek.getFlags > 0) {
>      if(yemek.getFlags == ubyte.max)

O doğru mu? Bütün günleri tek tek 'true' yapmış olsam "tüm hafta" anlamına gelmez mi? O durumda yedi gün 8 biti tam dolduramaz ve ubyte.max olmaz.

Ali

August 18
On Wednesday, 17 August 2022 at 17:38:19 UTC, Ali Çehreli wrote:
> On 8/17/22 10:30, Salih Dincer wrote:
>
> > bool tümHaftaTüket(bEnum8 yemek) {
> >    if(yemek.getFlags > 0) {
> >      if(yemek.getFlags == ubyte.max)
>
> O doğru mu? Bütün günleri tek tek 'true' yapmış olsam "tüm hafta" anlamına gelmez mi? O durumda yedi gün 8 biti tam dolduramaz ve ubyte.max olmaz.

Depresyona girme olayı tam olarak tümHaftaTüket() ile değil işaret ettiğim satırdaki (flags &= ~mask) saçmalığı ile alakalı.

Kolaya kaçtığım için üzgünüm çünkü ben pek tembelimdir :)

Yoksa kullanılmayan bit'leri (hiç olmayacak olan 8. günü) hesaplamadım. Sanırım 127'ye mi eşitlemem gerekiyordu ya neyse hesapla kastırmadım.

Zaten bu kod büyüyü göstermek için yeterince lezzetli. Enum'ları çok sık kullanan biri olarak bu static yapı ilelebet kütüphanemde duracak! Walter'a da bir teşekkür.

Kolay gelsin...

August 18
On 8/18/22 11:05, Salih Dincer wrote:

> Kolaya kaçtığım için üzgünüm çünkü ben pek tembelimdir :)

Hepimiz tembeliz. :) Enum'ın değerlerinin zaten birer birer artması gerekiyor. O yüzden şunlardan birisi olabilir:

// auto allBitsSet(E)() {
//   ubyte mask;

//   static foreach (mem; __traits(allMembers, E)) {
//     mixin ("mask |= 1 << E." ~ mem ~ ";");
//   }

//   return mask;
// }

auto allBitsSet(E)() {
  return 2 ^^ (E.max + 1) - 1;
}

Sonra:

/* static */ struct BoolEnum(E)
{
  enum ubyte allMask = allBitsSet!E();
  // ...
}

Ve yeni farkettim: D'de 'static'in modül düzeyinde bir anlamı yoktur.

Ali

August 19
On Thursday, 18 August 2022 at 18:05:43 UTC, Salih Dincer wrote:
> [...] bu kod büyüyü göstermek için yeterince lezzetli. Enum'ları çok sık kullanan biri olarak bu static yapı ilelebet kütüphanemde duracak!

Hala template olanağını yeterince usta bir şekilde kullanamayan bir çırak olarak söylüyorum ki aslında her şey bir büyü. Nedir bu büyü, adım adım anlatayım:

#alias, adı üstünde bir takma ad ve C'deki define gibi ama bence daha üstün ve D sayesinde çok yetenekli. Ama derleme zamanı olanağı,

#enum, eee onlar da öyle, yani derleme anında sayısal karşılığı da makine kodu içine gömülmüş adı/teksti(metni) de biliniyorlar.

=== ARA NOT ===
Yabancı forumun ilgili başlığında #Strawberries görmüşsünüzdür; Walter'ın katma (mixin) olanağı ile yaptığına karşılık opDispatch() kullanmayı deneyen (Andrey Zherikov) oldu. Sonra itirazlar gelince, yukardaki kodun son halini aldı. Yani orada (BoolEnum yapısına bağlı) bir işlev ya da eşitlenebilecek bir değişken yok. Evet, ben yardımcı işlevler ekledim ve bit'sel olarak en küçük ubyte türünde 8 bayrağımız var ve bu C geleneğinde define'lar ile yıllardır yapıla gelen bir şey aslında...
=== ARA NOT ===

#templates, bunun (şablonların) ne olduğunu ustaları daha iyi anlatacaktır ama diğerleri gibi derleme anı olanağı olduğu her halinden belli. İçinde alias ve enum neredeyse hiç eksik olmuyor. Ama bir de bakıyorsunuz ki şablon ile aynı isimde işlevler karşımıza çıkıyor. Her şey alıştığımız gibi. Yani kodlama çok tanıdık ve bu şablon kurallarını kim belirlemiş bilmiyorum ama çok az farklı kural var. Başa template geliyor ve Alice's Wonderworld'e hoşgeldiniz :)

Devam edelim...

- Statik olan foreach, #traits marifetiyle enum'un tüm üyeleri üzerinde geziniyor,

- Alias'lara yukarda değindim ve yine bir derleme anı olanağı olan #mixin ile aynı isimlerde takma adlarımız oluyor.

- Ama eşitliğin karşısında çalışma zamanı bir olanak olmadığına göre Impl() işlevi çalıştırılıyor ve şablon işlevleri ile ilişkilendiriliyor.

- Bitmedi! true aldığı parametre gidiyor bayrağın ilgili bit'ini zaten derleme anında 1 yaptı bile veya bool döndüren diğer işlev bulunduğu yere yine aynı şekilde false/true koyuyor.

Özetle kod yazarken, sadece alias ve enum'lar arasında (daha insancıl arayüz) değişiklik yaparak çok karmaşık bir algoritmayı yönetebilirsiniz. Tabi işin içine #Rokfor tadında #AA eklmek de ayrı bir #lezzet!

Sevgiler, saygılar...