Thread overview
copy mi put mu
Mar 29, 2023
Salih Dincer
Mar 29, 2023
Salih Dincer
Mar 29, 2023
Salih Dincer
Mar 29, 2023
Ali Çehreli
Mar 29, 2023
Salih Dincer
Mar 29, 2023
Ali Çehreli
March 29, 2023

Merhaba,

Aslında her ikisi birbirinden kıymetli ama aradaki farkı vurgulamak önemli. Özellikle de put()'un aslında bir şeyi bir yere koymasında çok adeta fill() gibi yapıp dolduruyor. Örneklere bakalım:

void main()
{
    import std.algorithm.mutation : kopyala = copy;
    import std.range : iDoldur = put;

    enum len = 10;
    auto buf = new int[len]; // önbellek
    auto RAK = [7, 1, 2, 3]; // rakamlar

    auto fark = len - RAK.length;
    auto rem = RAK.kopyala(buf);

    assert(buf[0..$ - fark] == [7, 1, 2, 3]);

    import std.algorithm : swap;

    buf[0].swap(rem[0]);
    assert(rem == [7, 0, 0, 0, 0, 0]);

    // rem'i DEVAMI ile doldur
    auto DEVAMI = [4, 5, 6, 7, 8, 9];
    rem.iDoldur(DEVAMI); // ile

    assert(buf == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

    import std.stdio : writeln;
    rem.writeln; // [] (boş çünkü tüketildi)

    // orta beşliyi eksileriyle doldur:
    auto orta5 = buf[2..$-3];
    orta5.iDoldur([-2, -3, -4, -5, -6]);
    buf.writeln; // [0, 1, -2, -3, -4, -5, -6, 7, 8, 9]
}

Her ikisinin de isimlerini Türkçe cümle ile uyumlu olacak şekilde değiştirdim. Dikkat edilirse kopyalandıktan sonra boşta kalan aralığı dilim olarak döndürmesi copy()'nin çok kıymetli olmasını sağlıyor.

Aynı şekilde put()'un ona verilen aralığı/dilimi tüketmesine de dikkat edin ve son bir not:

Sanki copy()'nin target'ı (destination) 2. parametreyken put()'da bu yer değiştirmiş. Yani put'lanan aslında solda, yani hedef 1. parametre.

Başarılar...

March 29, 2023

On Wednesday, 29 March 2023 at 09:01:26 UTC, Salih Dincer wrote:

>

Aynı şekilde put()'un ona verilen aralığı/dilimi tüketmesine de dikkat edin ...

Henüz put()'un kodlarına bakmadım ama yaptığı en temel olarak benim implement ettiğime benzer olmalı. Benzemeyense, (sanırım tür çıkarımı yapabilmesi için) dilimi bir değişken veya dinamik dizi olarak tanımlamalısınız. Belki put()'un ekstradan bir overloadına daha ihtiyaç vardır, bilemiyorum çünkü benim ki eksik kaldığı noktada çalışıyor! 😀

void main()
{
    import std.range : iDoldur = put;
auto slice = a[1..$-1];
    a[1..$-1].iDoldur([2, 3]);/*
    slice.iDoldur([2, 3]);//*/
    b[1..$-1].put([2, 3]);
    a.writeln("==", b);
} /* slice olmayınca Phobos put'u çalışmıyor!
onlineapp.d(39): Error: none of the overloads of template `std.range.primitives.put` are callable using argument types `!()(int[], int[])`
/dlang/dmd/linux/bin64/../../src/phobos/std/range/primitives.d(386):        Candidate is: `put(R, E)(ref R r, E e)`
//*/

void put(R)(R[] range, R[] source) {
  assert(source.length <= range.length);
  foreach(element; source)
  {
    range[0] = element;  // range.front()
    range = range[1..$]; // range popFront()
  }
}

Öğrenmeye devam!

March 29, 2023

On Wednesday, 29 March 2023 at 11:10:09 UTC, Salih Dincer wrote:

>

Öğrenmeye devam!

Bu konuyu Learn'e açtım:

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

March 29, 2023
On 3/29/23 04:10, Salih Dincer wrote:

> Henüz `put()`'un kodlarına bakmadım ama yaptığı en temel olarak benim
> implement ettiğime benzer olmalı.

Farkı; sen dilimlerle çalışıyorsun, o herhangi OutputRange ile.

Diğer forum konusuna daha bakmadım ama bir de 'ref' konusu var: Senin put() aynı dilim üzerinde bir kere daha çağırman için dilimin geri kalanını göstermen yeterli.

O ise, OutputRange'i tükettiğinden ikinci put() çağrısının nereye yapılacağı belli: Kaldığı yer. Onu da her OutputRange dilimlenebilen çeşitten olmadığından öyle yapmak zorunda.

Ali

March 29, 2023
On Wednesday, 29 March 2023 at 14:57:53 UTC, Ali Çehreli wrote:
> O ise, OutputRange'i tükettiğinden ikinci put() çağrısının nereye yapılacağı belli: Kaldığı yer. Onu da her OutputRange dilimlenebilen çeşitten olmadığından öyle yapmak zorunda.

Hocam, hani çoğu zaman aman `ref` kullanmayın, dikkatli kullanın ve mümkünse `const`lar ile kendinizi garantiye alın diyoruz ya...

Ama Phobos'un put'larına baktım da (bir doPut varmış!) şablon parametreleri hep ref. Hata vermesini ve neden böyle yapıldığını anlayabiliyorum. Sonuçta void bir sub-routine ve çevresi ile etkileşime geçmeli.

Geçmişteki onlarca tartışmaya bakılırsa neden put'un çok tartışmalı olduğu anlaşılır ya da anlaşılamadığı için böyle durumlara gebe olacağı tahmin edilebilir. Üstelik temelde copy'den hiç bir farkı yokken.

Bence Appender'daki veya başka türün put() üyesi olacağından (evet, UFCS nimetinden faydalanmayın diyorlar!) ve güçlü bir işlev olduğundan bunun private (hatta emekli) olup yerini copy'e bırakmalı ki bunu, yabancı forumda simple/standart version örneği ile kanıtladığımı zannediyorum.

Put, çok sakıncalı 😀


March 29, 2023
On 3/29/23 14:13, Salih Dincer wrote:

> Hocam, hani çoğu zaman aman `ref` kullanmayın,

Öyle diyor muyuz gerçekten? :) 'ref', kullanılması gereken yerde kullanılır. Genelde gerekmiyor çünkü çoğunlukla anlamsal olarak 'ref' göndermek istemiyoruz. Amacımız bir değer göndermek oluyor ve çoğu nesne temel türlerden oluşan ve hızlıca kopyalanan çeşitten olunca gönderiveriyoruz.

> dikkatli kullanın

Her konuda geçerli. :)

> ve
> mümkünse `const`lar ile kendinizi garantiye alın diyoruz ya...

Açıkça 'ref' yerine 'in' kullanmanın anlamsal olarak daha mantıklı ve doğru olduğunu görüyoruz. 'in' 'const'ı da içerdiğinden belki de en iyi çözüm o. (-preview=in olanağından bahsediyorum.)

> (bir doPut varmış!)

Ama 'private'.

> Üstelik temelde copy'den hiç bir farkı yokken.

Galiba dilimler için öyle oluyor. Özel bir amacı olan bir OutputRange nesnesi üzerinde farklı etkileri olabilir. Ama haklısın, fazla yakın kavramlar...

Ali