October 03, 2021

Merhaba,

Bugün yaptığımız Zoom toplantısı* inanılmaz verimli geçti...

Diyebilirim ki bu sene yaptıklarımızın toplamı ama konuştuklarımızdan küçük bir derleme yapmak istiyorum; yoksa çok vakit alacaktır! Hemen altına da kısaca olayı özetleyeceğim çünkü çok şey öğrendik. Mesela ben main() dışında onu ekleyen kurucu/yıkıcı olanağını bilmiyordum, iyi oldu :)

(*) https://forum.dlang.org/post/rkbjgzxqjjamhbkcfxyo@forum.dlang.org

import std.algorithm.mutation, std.stdio;
     /*        ^--burdan gelen swap() ile *
      * alttaki rSwap() farklıdır!        */

void rSwap (ref shared(int) x,
            ref shared(int) y) {
    x = x + y;
    y = x - y;
    x = x - y;
}

shared {
  int[] sD;
  int x, y;
}

static this() {
  sD ~= [80, 90, 100, 110];
  x = sD[0..1][0];
  y = sD[$-1..$][0];
}

void main() {
    /* main() sınıfı kurulurken sD[]'nin ilk
     * ve son elemanı değerleri x/y olur ve
     * aşağıda aritmetiksel olarak yer değişir:
     */

    x.rSwap(y);
    x.writeln(", ", y);
    sD.writeln(": sD dizisi değişemez...");
}

static ~this() {
  sD[$-1..$][0].swap
  (
    sD[0..1][0]
  );
  sD.writeln(": ama swap() değiştirir!");
}
/* Çıktısı:

110, 80
[80, 90, 100, 110]: sD dizisi değişemez...
[110, 90, 100, 80]: ama swap() değiştirir!

*/

Öncelikle alışık olmadığınız kodlama tarzı için kusura bakmayın; kanımca böyle rahat anlaşılıyor. Sırayla gidelim:

  • Yukarda aritmetik yer değiştirme (rSwap) ile yerleşik örneği (std.algorithm.mutation.swap) arasında bir karşılaştırma görülmekte. Ama yöntem önemli değil parametrelerin niteliğine dikkat!

  • rSwap() referans değeri alıyor ama x/y tıpkı sD[] gibi sıradan değiştirilebilir değişkenler, tek esprisi shared oluşu...

  • İşte bunlar işaretçi olmadığından ve/veya bir dilimden gelenin değerini tuttuğundan, main() içinde gerçekleşen yer değiştirme sD dizisinden bağımsız oldu, sorun değil ama devamında yine aynı parametreleri alabildiği için (burada bir soru**) sD[] değişiyor!

  • Program yıkıma uğradığı sırada (-bknz. ~this) yine aynı dilimler ile yer değiştiriliyor. Ama dikkat, sondaki [0]'a ile tek elemana referans işaret ettik.

(**) Sorum kısaca şu: swap() gibi kendi işlevlerimizi yapabilir miyiz? Yani bir aralık alıp onun işaret ettiği yerde işlem yapmak istesek nasıl mümkün olabilir?

Teşekkürler...

October 04, 2021
On 10/3/21 8:58 AM, Salih Dincer wrote:

> import std.algorithm.mutation, std.stdio;
>       /*        ^--burdan gelen swap() ile *
>        * alttaki rSwap() farklıdır!        */
>
> void rSwap (ref shared(int) x,
>              ref shared(int) y) {
>      x = x + y;
>      y = x - y;
>      x = x - y;
> }

> (**) Sorum kısaca şu: swap() gibi kendi işlevlerimizi yapabilir miyiz?

Soruyu doğru anladığımdan emin değilim ama tabii yazabiliriz. Örneğin, D'nin standart kütüphanesinin çok okunaklı olduğu söylenir. Biz de yazabiliriz. :)

> Yani bir aralık alıp onun işaret ettiği yerde işlem yapmak istesek nasıl
> mümkün olabilir?

Bunu da tam anlamıyorum galiba ama aralıkların farklı çeşitleri olduğundan, aklıma gelen iki işlev gösteriyorum. Birincisi, yalnızca RandomAccessRange çeşidinden aralıklarla işler. İkincisi InputRange'i yeterli bulur (tembel bir algoritmadır).

// Bu, RandomAccessRange gerektirir
void yarıla(R)(R aralık) {
  foreach (ref eleman; aralık) {
    eleman /= 2;
  }
}

unittest {
  auto dizi      = [0, 2, 42, -22];
  const beklenen = [0, 1, 21, -11];

  dizi.yarıla;
  assert(dizi == beklenen);
}

// Bu, InputRange'i yeterli bulur
auto yarılanmış(R)(R aralık) {
  import std.algorithm : map;
  return aralık.map!(e => e / 2);
}

unittest {
  import std.range;
  import std.algorithm;
  assert(6f.iota.yarılanmış.equal([0, 0.5, 1, 1.5, 2, 2.5]));
}

void main() {
}

Ali