Thread overview
September 02

Yeni bir şey öğrendim, şurda ve çalışan kod aşağıda. Kaynağındaki (evilrat'ın çözümü) sözde kod olduğu için çalışmıyor...

struct Alan
{
  int en, boy;
}
alias Oda = Alan[string];

void var_Mı(Value, Key, Func)
(Value[Key] liste, Key isim, in Func fun)
{
  if (auto adresi = isim in liste)
  {
    fun(*adresi, isim);

  } else {

    isim.writeln(" bulunamadı!");
  }
}

enum evinNeresi = [ "Mutfak", "Salon",
"Yatak Odası"];

import std.stdio;
void main()
{
  Oda evimde = [evinNeresi[0]: Alan(3, 5),
                evinNeresi[2]: Alan(7, 4)
  ];

  evimde.var_Mı(evinNeresi[2],
  // Alanı hesaplama, tabi listede varsa:
    (Alan oda, string isim)
    {
      auto alan = oda.en;
           alan *= oda.boy;
      isim.write(" m²'si: ", alan);
    }
  );
}

Bu kodda temel nokta var_Mı() ismindeki işlev. Öyle bir yardımcı ki bu, çağrışımsal dizilerle çalışırken her yerde kullanabilirsiniz ve kullandığınız yerde ona yeni bir kişilik katabilirsiniz.

Çünkü 2 parametreli (biri key) lambda işlev alıyor. Eğer işlem listede yoksa ya hiçbir şey yaptırmaz, ya hata kodu atabilir, ya da koddaki gibi sıradan bir uyarı yazdırabilirsiniz.

Not: Listeye (evimde dizisi) 0 ve 2 numaralı eleman ekleniyor, eğer uyarı mesajını görmek istersen 1 numarayı sorgulatmayı deneyin.

SDB@79

September 06

On Monday, 2 September 2024 at 18:07:42 UTC, Salih Dincer wrote:

>

Yeni bir şey öğrendim...

Yeni ama taaa eskilerden gelen bir şey daha:

    auto aa = ["bir": 1, "iki": 2];
    auto aaa = [1: 10, 2: 20];

    alias AA = typeof(aaa); //alias AA = int[string];

    static if (is(AA T : T[U], U : string))
    {
      typeid(U).writefln!"evet, istediğim gibi key bir %s";
      aa["bir"].writefln!"bir'in sayısal değeri = %s";
    }

Anlatımına gelince...

Diyelim ki bir işleve parametre olarak çağrışımsal dizi (AA: Ali hocanın kitabında Eşleme Tabloları) verdiniz. Derleme anında neyin indeks (key) neyin veri (value) olduğu belli ama sizin işlevinizi kullanan bunu bilmeyebilir. Yani tıpkı bu başlığın konusundaki gibi esnek bir işleviniz olabilir!

Öyleyse ve yine diyelim ki indeksleri dizge (string) değer olanlara göre muamele yapmanız gerektiğinde, yukardaki gibi bir static if() ile kodu güven altına alabilirsiniz. Özetle bu kodun tamamı programa dahil edilmeyecektir; taa ki takma isim (alias) AA, aa'nın türünü gösterene kadar. Çünkü o zaman doğru bir türü kullandığınız anlamına gelecek.

SDB@79

November 27

On Monday, 2 September 2024 at 18:07:42 UTC, Salih Dincer wrote:

>
void var_Mı(Value, Key, Func)
(Value[Key] liste, Key isim, in Func fun)
{
  if (auto adresi = isim in liste)
  {
    fun(*adresi, isim);

  } else {

    isim.writeln(" bulunamadı!");
  }
}

Hadi daha basit bir yaklaşımı ve "inline callback" işlevi yerine sıradan bir işlevi deneyelim. Öğrenci notlarını tutan bir listemiz olsun:

int[string] öğrenciNotları;

static this()
{
  öğrenciNotları = [
    "Ali": 85,
    "Ayşe": 90,
    "Ahmet": 78
  ];
}

Bir tane de basit bir callback function ekleyelim, ta taaa :)

void callback_fun(int not, string isim)
{
  isim.writeln(" isimli öğrencinin notu: ", not);
}

void main()
{
  auto notYazdır = &callback_fun;
  öğrenciNotları.var_Mı("Ayşe", notYazdır);
  öğrenciNotları.var_Mı("Mehmet", notYazdır);
}

Basit değil mi? Eee tabi harici bir veri tabanı daha basit olabilirdi. Ama bellekte hazırda duran ve gerçek zamanlı çalışan bir şeylere ihtiyaç duyduğunuzda hemen uygulayıverin.

SDB@79

November 27

Peki, yine aynı mantıkla dinamik rol tabanlı bir yetkilendirme nasıl olurdu! Önce yekileri (işlevleri) ve kullanıcıları tanımlayalım...

Buyrun tadından yenmez lezzetli (~90 satırlık) bir örnek:

import std.stdio;

alias fun = void function(string);
    void adminYetkisi(string isim) {
        isim.writeln(" yönetici yetkilerini kullanıyor.");
    }

    void editorYetkisi(string isim) {
        isim.writeln(" düzenleme yetkisini kullanıyor.");
    }

    void ziyaretciYetkisi(string isim) {
        isim.writeln(" sadece ziyaretçi, işlem yapılamaz.");
    }

void main()
{
  // Rolleri işlevlere bağlama:
  fun[string] roller = [
        "Admin": &adminYetkisi,
        "Editör": &editorYetkisi,
        "Ziyaretçi": &ziyaretciYetkisi
  ];

  // Kullanıcılar ve roller:
  string[string] kullanıcılar = [
        "Ali": "Admin",
        "Ayşe": "Editör",
        "Mehmet": "Ziyaretçi"
  ];

  foreach (isim, rol; kullanıcılar)
  {
    if (auto yetki = rol in roller)
    {
      (*yetki)(isim);
    }
    else
    {
      isim.writeln(" için geçersiz rol!");
    }
  }

  writeln("\n--- Ek Fonksiyonlar ---");

  void rolAta(string isim, string yeniRol)
  {
    if (yeniRol in roller)
    {
      kullanıcılar[isim] = yeniRol;
      isim.writeln(" rolü değiştirildi: ", yeniRol);
    }
    else
    {
      yeniRol.writeln(" geçersiz bir rol!");
    }
  }

  void rollerListele()
  {
    writeln("Mevcut roller:");
    foreach (rol; roller.keys)
    {
      rol.writefln!"- %s";
    }
  }

  void roleGöreKullanıcıListele(string rol)
  {
    if (rol in roller)
    {
      rol.writeln(" rolüne sahip kullanıcılar:");
      foreach (isim, kulRol; kullanıcılar)
      {
        if (kulRol == rol)
        {
          isim.writefln!"- %s";
        }
      }
    }
    else
    {
      rol.writeln(" geçersiz bir rol!");
    }
  }

  rolAta("Mehmet", "Editör");
  rolAta("Fatma", "Admin");
  writeln;

  rollerListele();
  writeln;

  roleGöreKullanıcıListele("Editör");
  roleGöreKullanıcıListele("Admin");
}/*
Ali yönetici yetkilerini kullanıyor.
Mehmet sadece ziyaretçi, işlem yapılamaz.
Ayşe düzenleme yetkisini kullanıyor.

--- Ek Fonksiyonlar ---
Mehmet rolü değiştirildi: Editör
Fatma rolü değiştirildi: Admin

Mevcut roller:
- Admin
- Editör
- Ziyaretçi

Editör rolüne sahip kullanıcılar:
- Mehmet
- Ayşe
Admin rolüne sahip kullanıcılar:
- Fatma
- Ali
*/

SDB@79

November 27
On 9/2/24 11:07 AM, Salih Dincer wrote:

> Çünkü 2 parametreli (biri key) lambda işlev alıyor. Eğer işlem listede
> yoksa ya hiçbir şey yaptırmaz, ya hata kodu atabilir, ya da koddaki gibi
> sıradan bir uyarı yazdırabilirsiniz.

Bana sanki ismi var_ise() olsa daha anlamlı olurmuş gibi geldi: "şu var ise şunu işlet" gibi.

Ali

November 28
On Thursday, 28 November 2024 at 03:29:56 UTC, Ali Çehreli wrote:
> On 9/2/24 11:07 AM, Salih Dincer wrote:
>
> > Çünkü 2 parametreli (biri key) lambda işlev alıyor. Eğer
> işlem listede
> > yoksa ya hiçbir şey yaptırmaz, ya hata kodu atabilir, ya da
> koddaki gibi
> > sıradan bir uyarı yazdırabilirsiniz.
>
> Bana sanki ismi var_ise() olsa daha anlamlı olurmuş gibi geldi: "şu var ise şunu işlet" gibi.
>
> Ali

Mantıklı...

SDB@79

November 30
On Thursday, 28 November 2024 at 03:29:56 UTC, Ali Çehreli wrote:
> On 9/2/24 11:07 AM, Salih Dincer wrote:
>
> > Çünkü 2 parametreli (biri key) lambda işlev alıyor. Eğer
> işlem listede
> > yoksa ya hiçbir şey yaptırmaz, ya hata kodu atabilir, ya da
> koddaki gibi
> > sıradan bir uyarı yazdırabilirsiniz.
>
> Bana sanki ismi var_ise() olsa daha anlamlı olurmuş gibi geldi: "şu var ise şunu işlet" gibi.
>
> Ali

Peki hocam, İngilizce karşılığı olarak sizce ne denilebilir?
- if_has
- contains
- exists

Kütüphanedeki (sanırım front-end kısmı object.d'de) AA implementasyonunda .get |.update |.require |.rehash vb. method'lar olduğunu biliyor ve kullanıyoruz. Bunun resmi dökümantasyonu şurada:

https://dlang.org/spec/hash-map.html

Ama sanki sezinlediğim bir şeyler eksik ki zaten dert yananlar ve/veya helper önerisinde bulunanlar çıkıyor. Hatta önümüzdeki büyük güncellemede nullable ile ilgili bir şeyler (ayrıntısını bilmiyorum) olacak sanırım. Neyse, C++'da da (unique_map) bu ilişkisel/çağrışımsal diziler çok popüler. Yapılabilecekler hayalleriniz iler sınırlı, örneğin bir HOF?

SDB@79
November 30
On 11/30/24 2:57 AM, Salih Dincer wrote:

>> Bana sanki ismi var_ise() olsa daha anlamlı olurmuş gibi geldi: "şu
>> var ise şunu işlet" gibi.
>>
>> Ali
>
> Peki hocam, İngilizce karşılığı olarak sizce ne denilebilir?
> - if_has
> - contains
> - exists

Zor. Daha önceden 'maybe'den yararlanıldığını görmüştüm ama o da tam açık olmuyor: executeMaybe.

Belki de varolan 'update'e benzer olarak yalnızca 'execute' veya 'executeOn' denir ve bulunmadığında ne yapılacağı da ikinci bir lambdayla belrtilir:

  https://dlang.org/spec/hash-map.html#advanced_updating

aa.executeOn("key",
             (int i) => writeln("varmış: ", i),
             () => writeln("yokmuş"));

İkinci lambdanın varsayılan değeri null olur ve gerekmiyorsa belirtilmez:

aa.executeOn("key",
             (int i) => writeln("varmış: ", i));

Veya executeIf mi denir?

Ali

December 01

On Saturday, 30 November 2024 at 19:53:22 UTC, Ali Çehreli wrote:

>

Zor...
...
Veya executeIf mi denir?

Hocam, bence biz programcılar tıpkı savaşçılar gibiyiz; parçalara bölmeyi çok seviyoruz, tek farkla: Biz parçala & yoket yerine parçalayarak çözüm üreti tercih ediyoruz. Belki de bir nakışcı/hattat edasıyla sevdiğim şeyi yapıyorum:

Sorunu, tek tek parçalara bölerek işle ve ortaya bir sanat çıkar/çözüm üret. Şurada değindiğim, aşağıda özetlediğim bunlardan biri...

1. adım için hasKey() ve elemanı döndürür ve sanki bir helper gibi çalışır,

2. adım için changeBy() ile tıpkı bir HOF gibi davranıp değer döndürmeden değişiklip yapılıp yapılmayacağını, gereksiz olup olmadığını kontrol eder ama kullanıcıdan bunun onayını da alabilir:

void main()
{
  with (Yetki)
  {
    auto user = [
       "Ali"    : Admin,
       "Ayşe"   : Editör,
       "Mehmet" : Ziyaretçi
    ];

    try
    {
      user.hasKey("Ayşem")
          .changeBy(Editör, (Yetki y)
            => y.format!"Yeni Yetki: %s"
          );
    }
    catch (HataAA!Yetki e) {
      e.msg.write;

    }
    catch (HataAA!string e) {
      e.msg.write;
      e.key.writefln!" çünkü kullanıcı (%s) bulunamadı!";
    }
  }
}

alias hasKey = step1;
alias changeBy = step2;

import std;

enum Yetki {
    Ziyaretçi, Editör, Admin
}

class HataAA(K) : Throwable {
    K key;
    this(string msg, K key) {
        super(msg);
        this.key = key;
    }
}

// STEP1: return pointer
auto step1(A, K)(A array, K key)
{
    if (auto result = key in array)
    {
        return result;

    } else throw new HataAA!K("Hata: 404", key);
}

// STEP2: no return
void step2(E, V, F)(E element, V value, F func)
{
  auto öncekiYetki = *element;
  if (öncekiYetki != value)
  {
    writeln("Yetkiyi değiştirmek ister misiniz? (E/H)");
    string cevap = "h";//readln().strip();
    if (cevap.toUpper == "E")
    {
      öncekiYetki.writeln(" yetkisi değiştirilecek...");
      *element = value;
       func(*element).writeln;
    } else throw new HataAA!V("505:  Yetki değişikliği yapılmadı, ", value);
  } else throw new HataAA!V("606: Yetki zaten eşleşiyor.", value);
}

Bu kod bir taşla birkaç kuş vuruyor. Önce bilerek tek harf farkla "Ayşem" yazarak 404 hatasını yakalarıyorum. Sonra m harfini silin 505'i yakaladığını görün ve sonra cevap olarak h yerine E veya e yazın. Böylece sırasıyla uydurulmuş 505 ve 606 hatalarını yakaladığını ama programın göçmediğini göreceksiniz.

Tabi baştan beri konuştuğumuz ve İngilizce'ye çevirmeninin zor olduğu işlevi ikiye bölmek akıllıca olsa da callback fonksiyonunu (CBF) inline olarak satıriçi yapmak biraz uyduruk oldu. Çünkü gerçek bir high-order fonksiyonu (HOF) için acaba klavyeden soru sorma yeteneğini CBF mi yapmalıydım?

Özetle parçalara bölebilmek güzel ama seçtiğim işlev isimleri (hasKey & changeBy) yeterince anlamlı oldu mu?

SDB@79