March 28, 2022

Merhaba,

Henüz inout'u olaylarını (buna, in ve out da eklenebilir) tam anlamamışken bir süredir şu alışık olduğumuz return'den farklı bir şeyler dönüp dolaşıyor, örneğin şu güncel başlık:

https://forum.dlang.org/thread/vvchetayjctvsrktjrrp@forum.dlang.org

Bunu denemek için soru/cevaplarda yazılanları şurada (online editor ile çalıştırılacak şekilde) derledim ve çıkan sonuç da şöyle:

onlineapp.Foo: 42
onlineapp.Bar: 41
eşitler
core.exception.AssertError@onlineapp.d(40): değiller
----------------
??:? _d_assert_msg [0x557ffe7c4378]
./onlineapp.d:40 pure nothrow @nogc @safe immutable(char)[] onlineapp.main().eşitler_mi() [0x557ffe7a32d8]
./onlineapp.d:50 _Dmain [0x557ffe7a3279]

Aslında, çıkan hata da dahil her şey istendiği gibi çalışıyor: Yani biri referans nesnesi olan Foo & Bar, ikişerli şekilde yarı otomatik ve init & setX ikilisi ile ilginç ve tuhaf şekilde kuruluyor...

Elbette başlığı açana sormak lazım; neden bu şekilde bir şey yapmış ama foo & bar ile fun & gun kopyalarının sahip olduğu üye (int x) istediğimiz değerleri alıyor. Meşhur set eden işlevimiz şu:

int* setX(T)(return auto ref T t)
{
  static if(is(T == class))
  {
    return &t.x;
  }
  else static if(is(T == struct) && __traits(isRef, t))
  {
    return &t.x;
  }
  else
  {
    static assert(0, "no impl " ~ T.stringof);
  }
}

Yaptığı şey basit çünkü soruyu soran, yapı ve sınıf için ayrı ayrı yardımcı işlev tanımlamadan statik yapıyla bir taşla 2 kuş vurmak istiyor. Gelen cevaba bakılırsa, hiçbir derleme hatası olmayacak şekilde bunu başaran bir işlevimiz var. Acaba bu şekilde x'i değiştirmenin ne faydası var ve return ref şart mı? Gerçi bu konuyu anlamak için şuradaki örnekler daha mantıklı görünüyor:

https://dlang.org/spec/function.html#return-ref-parameters

Teşekkürler...

March 28, 2022
On 3/28/22 11:43, Salih Dincer wrote:

> https://forum.dlang.org/thread/vvchetayjctvsrktjrrp@forum.dlang.org

Onu görmüştüm. Şimdi oraya bir yanıt da ben yazdım.

> Bunu denemek için soru/cevaplarda yazılanları

Birazını buraya kopyalıyorum:

> import std.stdio;
>
> struct Foo {
>   int x;
>
>   void init(int value) { *setX(this) = value; }
> }

Üye ismi olarak 'init' kullanılması önerilmez çünkü her türde zaten bulunan .init niteliği ile karışır.

> int* setX(T)(return auto ref T t) {
>   static if(is(T == class)) return &t.x;
>   else static if(is(T == struct) && __traits(isRef, t))
>     return &t.x;
>   else static assert(0, "no impl " ~ T.stringof);
> }

İki 'static if'te de aynı ifade olduğuna göre şununla aynı olmalı:

int* setX(T)(return auto ref T t) {
  static if(is(T == class) ||
            (is(T == struct) && __traits(isRef, t))) {

    return &t.x;  // AYNI İFADE

  } else {
    static assert(0, "no impl " ~ T.stringof);
   }
}

>   typeid(foo).writeln(": ", foo.x);

İlgisiz yan konu olarak, bir kişisel tercih (veya rahatsızlık :) ): Öyle yazınca typeid(foo)'yu ön plana çıkartılıyormuş gibi oluyor. Halbuki oradaki işlev birşeylerin çıktıya yazdırılması. O yüzden, ben writeln'in ön planda olması gerektiğini düşünüyorum. Yani, neden üç parametreden birincisi diğerlerinde ayrılsın diye düşünüyorum ve daha okunaklı bulduğum için şöyle yazıyorum:

  writeln(typeid(foo), ": ", foo.x);

Yalan söyledim. :) Aslında

  writefln!"%s: %s"(typeid(foo), foo.x);

diye yazıyorum.

> Yaptığı şey basit çünkü soruyu soran, yapı ve sınıf için ayrı ayrı
> yardımcı işlev tanımlamadan statik yapıyla bir taşla 2 kuş vurmak
> istiyor.

O konuya da yazdığım gibi, şu da olur:

int* setX(T)(auto ref T t) {
  return &t.x;
}

> ```return ref``` şart mı?

Burada yarar sağladığı bir örnek bulamadım ama 'return ref' sinsi bir hatayı yakalamak için kullanılır. Şurada zaten bir örnek vermişim:


http://ddili.org/ders/d/islev_parametreleri.html#ix_islev_parametreleri.return,%20parametre

Ben bu forum konusundaki örnekte yararını göremedim çünkü 'return' kullanılmasa da tehlikeli durumda derleyici zaten uyarıyor. (?) İşte, 'return' kullanmadan

int* setX(T)(auto ref T t) {
  return &t.x;
}

İşte tehlikeli kullanım:

  auto ptr = setX(Foo(100));

Derleyici zaten hata veriyor. Hata vermesi iyi ama neden bu programda kullanımının gereğini göremiyorum acaba. İngilizce foruma da yazdım. Birisi aydınlatabilir...

Ali