Thread overview
Özelleştirilmiş aralıklar için en doğru save() yöntemi nedir?
Nov 03, 2022
Salih Dincer
Nov 03, 2022
Ali Çehreli
Nov 04, 2022
Salih Dincer
Nov 04, 2022
Ali Çehreli
Nov 05, 2022
Salih Dincer
November 03, 2022

Merhaba,

Bugün şu kod sayesinde iota'nın save() özelliği olmadığını öğrendim:

import std.stdio;
import std.range;

void main()
{
  foreach(num; //inclusiveRange!char(65, 69).chunks(3)/*
              iota!char('a', 'f').chunks(3)//*/
  ) {
		num.writeln(": ", num.walkLength);
  }
} /*
: 3
: 2
*/

Normalda olması gereken çıktı aşağıdaki gibi olmalıydı. Bunu denemek için yorum karakterlerini silip Ali hocanın ile birlikte geliştirdiğimiz iota'nın alternatifine geçiş yapmalısınız.

>

ABC: 3
DE: 2

O yapıda (inclusiveRange) basitçe auto save() => this; özelliği var ve walkLength() aralığı saymadan evvel bunu kullanıyor olmalı. Çünkü writeln() tüketmesine de fırsat veriyor.

Peki sahip olduğumuz aralığı kaydetmenin en doğru yöntemi bu mudur, bu kadar basit midir?

Teşekkürler...

November 03, 2022
On 11/3/22 00:36, Salih Dincer wrote:

> Bugün şu kod sayesinde `iota`'nın `save()` özelliği olmadığını öğrendim:

Aslında vardır:

import std.range : iota;

void main() {
    auto a = iota(10);
    a.popFront();
    auto b = a.save();     // <-- Burada
    assert(b.front == 1);
}

Demek ki senin programınla ilgili daha karmaşık bir durum var...

> ```d
> import std.stdio;
> import std.range;
>
> void main()
> {
>    foreach(num; //inclusiveRange!char(65, 69).chunks(3)/*
>                iota!char('a', 'f').chunks(3)//*/
>    ) {
>          num.writeln(": ", num.walkLength);

İngilizce forumda da gördüğüm gibi, galiba burada num.save istiyoruz. Yoksa num.walkLength tükettikçe num.writeln'a yazacak bir şey kalmıyor.

Dolayısıyla, iota'nın değil, Chunk'ın save'inin bulunup bulunmadığından söz edebiliriz:

  https://dlang.org/phobos/std_range.html#.Chunks.save

Orada söylediğine göre, Chunks.save, ancak chunks'a verilen aralık ForwardRange olduğunda varmış. Bakalım:

pragma(msg, isForwardRange!(typeof(iota!char('a', 'f'))));

O ifade 'false' yazdırıyor. Onun nedeni de herhalde iota!char'ın eleman türünün dchar olmasıdır. (Hani char aslında yazı karakteri değildir de UTF-8 kodudur ya...)

Bende bu kadar... char yerine byte vs. kullanınca olur herhalde. char değerleri teker teker arttırmak ve sonra harf vs. ummak pek doğru bir beklenti değil galiba.

Ali

November 04, 2022

On Thursday, 3 November 2022 at 14:45:15 UTC, Ali Çehreli wrote:

>

On 11/3/22 00:36, Salih Dincer wrote:

Dolayısıyla, iota'nın değil, Chunk'ın save'inin bulunup bulunmadığından söz edebiliriz:

https://dlang.org/phobos/std_range.html#.Chunks.save

Haklısınız hocam, sorun Chunk'da:

import std.stdio;
import std.range;

//version = NoError;
void main()
{
  int viewType = 1;
  version(NoError)
  {
		foreach(num; //inclusiveRange!char(65, 69)/*
								iota!ubyte(65, 70)//*/
								.chunks(3))
		{
			if(viewType--) typeof(num).stringof.writeln(" =>");
			num.writeln(", ", num.walkLength, ": ");
		}
		writeln("<-- iras!char: okay(type == Take)");
		writeln("iota!ubyte: okay(type == Result)");

  } else {
	
		foreach(num; iota!char('a', 'f')/*
								iota!char(65, 70)//*/
								.chunks(3))
		{
			if(viewType--) typeof(num).stringof.writeln(" =>");
			num.writeln(", ", num.walkLength, ": ");
	
		}
		writeln("<-- iota ASCII: false(type == Chunk)");
		writeln("iota non-ASCII: okay(type == Result)");
  }
}

Yabancı forumdan bağımsız 2. ve asıl sorumun cevabını alamadım. Sahi en uygun .save() yöntemi nedir? Yapıdan yapıya göre değişir mi?

Teşekkürler...

November 04, 2022
On 11/4/22 01:45, Salih Dincer wrote:
> On Thursday, 3 November 2022 at 14:45:15 UTC, Ali Çehreli wrote:
>> On 11/3/22 00:36, Salih Dincer wrote:
>>
>> Dolayısıyla, iota'nın değil, Chunk'ın save'inin bulunup
>> bulunmadığından söz edebiliriz:
>>
>>   https://dlang.org/phobos/std_range.html#.Chunks.save
>>
>
> Haklısınız hocam, sorun Chunk'da:

Ama o da iota!char save'i sun(a)madığı için sunamıyor.

iota!char'ın neden mantıklı olmadığını biraz daha düşündüm. UTF-8 kod biriminden bahsediyoruz. Tanımı şöyle:

  https://en.wikipedia.org/wiki/UTF-8#Encoding

Yani, 10 diye başlayan değerler, Unicode karakterinin ikinci, üçüncü, ve dördüncü kodlama baytı oluyorlar.

O zaman aşağıdaki pek anlamlı değildir herhalde.

  iota!char(0b1000_0000)

Belki de anlamlıdır çünkü belki bir Unicode kütüphanesini test etmek için baş karakterin arkasından kullanmak üzere ikinci baytla üretiyoruzdur. Bilmiyorum...

> uygun .save() yöntemi nedir? Yapıdan yapıya göre değişir mi?

Evet, yapıya göre değişir. Amaç, .save'in döndürdüğü aralığın, döndüren aralıktan eleman üretme konusunda tamamen bağımsız olmasıdır.

Şu olur çünkü her üye kopyalanır. (Başka deyişle, burada hiç "indirection" yok.)

struct Fibonacci {
  int şimdiki;
  int sonraki;

  auto save() {
    return this;
  }

  // ...
}

Ama şu olmaz çünkü iki S nesnesi aynı asıl aralığı kullanmış olurlar:

class AsılAralık {
  // ...
}

struct S {
    AsılAralık aralık;  // <-- Dikkat: Referans türü

    auto save() {
        return this;
    }

    // ...
}

Onun doğru olması için AsılAralık'ın bir kopyasının alınması gerekir.

Ali

November 05, 2022
On Friday, 4 November 2022 at 17:59:55 UTC, Ali Çehreli wrote:
> Onun doğru olması için AsılAralık'ın bir kopyasının alınması gerekir.

Tahmin ettiğim gibi, teşekkürler...

Bu arada bu başlık iyi bir şeye vesile oldu. Çünkü iota() hakkında o kadar yazıp çizmemize rağmen sürüm 2.0.99'de bile save() ve length() kullanım dışıymış. ArtıK Paul'un açtığı hata bildirimi sayesinde sorun düzeldi:

https://issues.dlang.org/show_bug.cgi?id=23453

Dileyen walkLength() de kullanabilir aralık gereksiz tükenmez ya da length sayesinde ekstra bir şeye ihtiyaç duyulmaz. Gecelik sürümde şu kod artık doğru çalışıyor:

  auto range = iota('a', 'g', char(1));
  foreach(chr; range.chunks(3)) {
    chr.write(": ", chr.walkLength, " ");
    assert(chr.length == chr.walkLength);
  } // abc: 3 def: 3

Sevgiler, saygılar...