Thread overview
Voldemort Types konusu 2
Feb 27, 2022
Salih Dincer
Feb 27, 2022
Ali Çehreli
Feb 27, 2022
Ali Çehreli
Feb 28, 2022
Salih Dincer
Apr 06, 2022
Salih Dincer
Dec 01, 2022
Salih Dincer
February 27, 2022

Merhaba,

Şurda başlayan ama birazdan iki ilginç sonuca varacağımız aşağıdaki örnek de bir başka güzel! Aslında Voldemort kavramından uzaklaştım çünkü 2. bir özellik için yapıyı işlev dışına çıkardım:

struct SliceString(string E)
{
  import len = std.string;

  long index, back, next = -1;

  string data;

  this(string data)
  {
    this.data = data;
    this.index = len.split(data).length;
  }

  @system
  {
    bool empty()
    {
      return index < 0;
    }

    auto front()
    {
      return data[back..next];
    }

    void popFront()
    {
      --index;
      back = ++next;
      next = len.indexOf(data, E, next);
      if(next == -1) next = data.length;
    }
  }

  auto popIndex()
  {
    this.popFront();
    return [back, next];
  }
}

auto split(string E)(string data)
{
  auto s = SliceString!E(data);
       s.popFront();

  return s;
}

import std.stdio;

void main()
{
  auto dizge = "bu bir denemedir";
  auto s = SliceString!" "(dizge);

  long[2] dilim_paramterleri = s.popIndex;
  while(!s.empty)
  {
    dilim_paramterleri.writeln;
    dilim_paramterleri = s.popIndex;
  } // popIndex(): [0, 2] [3, 6] [7, 16]

  auto birAralık = dizge.split!" ";
  foreach(r; birAralık)
    r.writeln;

  enum boşDeğil = false; // Voldemort Types örneğinde boştu!
  assert(birAralık.empty == boşDeğil);
} /* ŞURDA BAŞLADI:

https://forum.dlang.org/post/zdroayoznvcqkdzhwwfu@forum.dlang.org
   */

Yukarda 2. özelliği popIndex() olarak görmektesiniz. Yani bir nevi split() yapıyor ama dizgenin dilimlediği baş/son parametrelerini döndürüyor. Özetle yapıya iki özellik verdik. Diğer ilginç nokta ise şu:

Önceki Voldemort örneğinde, kod biterken işaret ettiğim gibi yapı foreach() tarafından tüketiliyordu (oysa önce yedeğini alırdı, alamadı demek ki!) ve birAralık boş kalmaya devam ediyordu. Burda ise boş yani yapıyı işlev dışına almak daha akıllıca olabilir.

D çok güzel, sizce değil mi?

February 27, 2022
On 2/27/22 04:49, Salih Dincer wrote:
> Merhaba,
>
> [Şurda
> başlayan](https://forum.dlang.org/post/zdroayoznvcqkdzhwwfu@forum.dlang.org) 

> ama birazdan iki ilginç sonuca varacağımız aşağıdaki örnek de bir başka
> güzel! Aslında Voldemort kavramından uzaklaştım çünkü 2. bir özellik
> için yapıyı işlev dışına çıkardım:
>
> ```d
> struct SliceString(string E)
> {
>    import len = std.string;

"len" anlaşılamadı. ;)

>      this.index = len.split(data).length;

Bunu önceki konuda da konuştuk ama o gereksizce pahalı bir işlem olabilir çünkü .split heveslidir: data'yı parçalara ayırır ve onlardan bir dizi üretir. O dizinin yeri bellekten yeni ayrılan bir alandır. İşin kötü tarafı, oluşturulan dizi ve bellek hiç kullanılmıyor bile. (İşin iyi tarafı, elemanlar için farklı yer ayrılmaz; dizinin elemanları 'data'nın içindeki karakterleri gösterirler ama yine de asıl dizi için bellek ayrılır.)

Onun yerine şu da olabilir:

     import std.range : walkLength;
     this.index = len.splitter(data).walkLength;

Ama bence en iyisi length'e gerek olmasa çok daha az iş yapmakla yetinebiliriz.

>      auto front()
>      {
>        return data[back..next];
>      }

Galiba splitter gibi işleyen bir aralık bu. Ama indeksler kullandığı için senin aralık RandomAccessRange istiyor. Yani aslında bir dizi gerektiriyor. Örneğin şöyle bir aralıkla kullanılamaz:

  stdin.byLine.take(42)

std.algorithm.splitter'ın (ve çoğu Phobos aralığının) yararı, olabildiğince az şey istemeleridir. Örneğin, bir iş InputRange ile de yapılabiliyorsa RandomAccessRange gerektirmek kullanışlılığı düşürür.

Ali

February 27, 2022
On 2/27/22 12:48, Ali Çehreli wrote:
> Örneğin şöyle bir aralıkla kullanılamaz:
>
>    stdin.byLine.take(42)
>

Biraz uydurmuşum çünkü std.algorithm.splitter da öyle bir aralıkla doğrudan kullanılamaz. Ama şöyle kullanılabilir:

import std.stdio;
import std.range;
import std.algorithm;

void main() {
  auto sözcükler = stdin
                   .byLine
                   .take(42)
                   .map!splitter
                   .joiner;
  writefln!"%-(%s %)"(sözcükler);
}

O programı şöyle deneyebiliriz:

  $ cat deneme.d | ./deneme

Dosyanın ilk 42 satırındaki sözcükleri boşluklarla ayrılmış olarak yazdırır. O programın yararı, hiç bellek ayırmıyor olmasıdır. (byLine'ın aynı ara belleği kullandığını da unutmamak gerekir. Sözcükler sonrası için depolanacaklarsa .byLineCopy kullanılmalıdır.)

Ali

February 28, 2022

Aşağıdaki mesajımı tam göndermek üzereydim ki şu dizgi ile denediğimde sorumun cevabımı aldım. Whitespace character mevzusu yani birden fazla karakter üzerinden split() varmış, vakit ayırdığınız için teşekkürler yine de :)

auto str = `
bu bir bey
az bardak`;

On Sunday, 27 February 2022 at 21:07:41 UTC, Ali Çehreli wrote:

>

On 2/27/22 12:48, Ali Çehreli wrote:

import std.stdio;
import std.range;
import std.algorithm;

void main() {
  auto sözcükler = stdin
                   .byLine
                   .take(42)
                   .map!splitter
                   .joiner;
  writefln!"%-(%s %)"(sözcükler);
}

Açıklamalar ve bu lezzetli örnekler için teşekkürler hocam. Çok verimli ve güzel bir gün geçirdim. Tabi hala anlamadığım şeyler var, çözeceğim inşaallah. Misal, aşağıdaki 7 satırlık örneğin gizlenen satırını açtığımızda (5. satıra // koymak yeterli) istediğimiz 4 sayısını alıyoruz...

import std.algorithm : splitter;
import std.range : walkLength;
void main() {
  auto str = " bu bir beyaz bardak ";
  str.splitter(' ').walkLength.writeln;/* 6
  str.splitter.walkLength.writeln;    //* 4 */
}

Ancak şu yukardaki haliyle neden 6 alıyoruz? Öyle ya, bu tür separate özelliğine sahip komutlar ayraçı (separator) yok sayar ve arada kalanları dizi/aralık olarak döndürür. Aynısını dizi döndüren split()’de de gördüm. Tabi sayısını length ile almak zorunda kaldım ve evet:

Sayıyı almak için split() kullanmak pahalı bir işlemmiş. walkLength aralıklarla çalıştığı için çok leziz görünüyor.

Herhalde str’nin baş ve sonunda boşluk olmasına rağmen 2. durumda ayraç vermediğimiz için strip() işlemi (<--bu sefer kastettiğim tam olarak bu) uygulanıyor olmalı. Ne dersiniz?

Teşekkürler...

April 06, 2022

Güncelleme:

/* D Compiler: DMD v2.094.1
 *
 * sliceString.d (27.02.2022)
 * Updates: walkLength, dup, drop,
 *          elementPos : (06.02.2022)
 */

struct SliceString(string E)
{
  import std.string : split, scan = indexOf;
  import std.range : walkLength;

  long index, back, next = -1;
  string data;

  this(string data)
  {
    this.data = data;
    this.index = data.split(E).walkLength;
  }

  @system
  {
    bool empty()
    {
      return index < 0;
    }

    auto front()
    {
      return data[back..next];
    }

    void popFront()
    {
      --index;
      back = ++next;
      next = scan(data, E, next);
      if(next == -1) next = data.length;
    }

    SliceString dup()
    {
	  return this;
	}
  }

  @property popIndex()
  {
    scope(exit) this.popFront();
    return [back, next];
  }

  @property elementsPos()
  {
    long[][] result;
    while(!empty)
      result ~= popIndex;
    return result;
  }

  @property drop()
  {
    string result;
    foreach(str; this)
      result ~= str;
    return result;
  }
}

auto sliceOff(string E)(string data)
{
  //import sdb.container;
  auto s = SliceString!E(data);
       s.popFront();

  return s;
}

import std.stdio;

void main()
{
  auto str = "abcdefgdh";
  auto slc =  str.sliceOff!"d";

  foreach(s; slc)
    s.writeln;

  slc.elementsPos.writefln!"%-(%s\n%)";
  assert(slc.empty);

  str.sliceOff!"d"
     .drop
     .writeln;

} /* ŞURASI GÜNCELLEMEYE VESİLE OLDU:

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

   */
December 01, 2022

On Wednesday, 6 April 2022 at 09:19:39 UTC, Salih Dincer wrote:

>

Güncelleme:

Şimdi v2.1, aslında 3 üzerine çalışıyorum ama ilgi olmadığı için üst sürümleri artık paylaşmayacağım. Tek yaptığım düzenleme drop()'u fiilen kaldırıp yerine replace() getirmek oldu:

  alias drop = replace;
  @property replace(string alternate = "")
  {
    string result;
    if(alternate.length) {
      auto r = dup;
      for(; r.index > 0; r.popFront) {
        result ~= r.front;
        result ~= alternate;
      }
      result ~= r.front;
    } else foreach(r; this) result ~= r;
    return result;
  }

Tabi alias marifetiyle 1 taşla 2 kuş vurabileceğimi düşündüm. Netice ise basit bir örnekle şöyle gösterilebilir:

import std.stdio;

void main()
{
    auto den = "bu bir den eme";
    auto slc = den.sliceOff!" ";

    slc.drop.writeln;
    slc.replace("_").writeln;
}
/* ÇIKTISI:
bubirdeneme
bu_bir_den_eme
*/

Kolaylıklar...