Thread overview
assumeUnique() kullanırken...
Oct 20, 2022
Salih Dincer
Oct 20, 2022
Erdem
Oct 20, 2022
Salih Dincer
Oct 20, 2022
Salih Dincer
Oct 20, 2022
Erdem Demir
Oct 20, 2022
Ali Çehreli
Oct 21, 2022
Erdem
Oct 21, 2022
Ali Çehreli
Oct 21, 2022
Ali Çehreli
October 20, 2022

Merhaba,

Konuyla ilgili olarak örneklere (kodları biraz değiştirdim) benimle alakalı olmayan güncelleme gelmiş. Fark edince hemen konuyu aşağıda inceledim; önce kötü örnek önerilen dönüşü yöntemiyle ve main()'den sonra iyi örnek std.exception bağımlılığı olmadan nakletmeye çalıştım...

Kötü örnek dışarıdan bir private char[] buffer kullanırken iyi örnek yerel, yani kendine özel char[] privateBuffer ile önbellekleme yapıyor. Bir önbellek üzerinde metinlerle çalışırken ve bunu buffer üzerinden değil de değişmez yani immutable olarak aktarmak isterseniz dikkat etmenizde fayda var:

import std.conv, std.stdio;

/// KÖTÜ ÖRNEK ///
string badLetters(char first = 'a', char last = 'f')
in(first < last) {
  char[] sneaky = buffer; // sneaky bir dilim
  sneaky.length = last - first + 1;
  foreach (i, ref e; sneaky)
  {
    e = cast(char)(first + i);
  }
  //return assumeUnique(sneaky);/* bu durumda önerilen:
  return to!(string)(sneaky); //*/
}
private char[] buffer;
/// KÖTÜ ÖRNEK ///

void main()
{
  buffer ~= ".Dlang.";
  auto bad = badLetters();
  typeid(bad).writeln(": ", bad);

  buffer.writeln;

  auto fine = fineLetters();
  typeid(fine).writeln(": ", fine);
}

/// İYİ ÖRNEK ///
string fineLetters(char first = 'a', char last = 'f')
in(first < last) {
  char[] privateBuffer = new char[last - first + 1];
  foreach (i, ref e; privateBuffer)
  {
    e = cast(char)(first + i);
  }
  return assumeUnique(privateBuffer);
}
/// İYİ ÖRNEK ///

//import std.exception;/*
pure nothrow:
auto assumeUnique(T)(T[] array) {
    return .assumeUnique(array);
}
auto assumeUnique(T)(ref T[] array) {
    auto result = cast(immutable(T)[]) array;
    array = null;
    return result;
}
auto assumeUnique(T, U)(ref T[U] array){
    auto result = cast(immutable(T[U])) array;
    array = null;
    return result;
}
//*/

Başarılar...

October 20, 2022

On Thursday, 20 October 2022 at 08:33:51 UTC, Salih Dincer wrote:

>

Merhaba,

Konuyla ilgili olarak örneklere (kodları biraz değiştirdim) benimle alakalı olmayan güncelleme gelmiş. Fark edince hemen konuyu aşağıda inceledim; önce kötü örnek önerilen dönüşü yöntemiyle ve main()'den sonra iyi örnek std.exception bağımlılığı olmadan nakletmeye çalıştım...

[...]

Salih assunmeUnique ne ise yariyor ve nerelerde kullaniliyor benim gibi bilmeyen birine anlatabilir misin biraz. Is yerindeyim biraz baktim D sayfasina ama anlayamadim.

October 20, 2022

On Thursday, 20 October 2022 at 12:37:05 UTC, Erdem wrote:

>

Salih assunmeUnique ne ise yariyor ve nerelerde kullaniliyor benim gibi bilmeyen birine anlatabilir misin biraz. Is yerindeyim biraz baktim D sayfasina ama anlayamadim.

Basitçe değiştirilebilir diziyi alıp immutable döndürüyor ama koda bakarsan ref alıyor, kaynağı null yapıp bağını koparıyor!

Sevgiler, saygılar...

October 20, 2022

Tekrar Merhaba,

Kendi türümle denememiştim. Şimdi eve geldim ve hemen denedim 😀

struct S {
  int i;
  string s;
}
void main()
{
  //auto biriki = [2, 1];/*
  auto biriki = [
    S(2, "iki"),
    S(1, "bir")
  ];//*/

  //auto ikibir = biriki.dup;/*

  import std.exception : assumeUnique;
  auto ikibir = biriki.assumeUnique;/*/

  import std.algorithm.mutation : swap;
  biriki[0].swap(biriki[1]);//*/

  import std.stdio;
  biriki.writeln; // [1, 2]
  ikibir.writeln; // [2, 1]

} /* swap ile birlikte assumeUnique de açılırsa:
  core.exception.RangeError@assumeUnique.d(35):
  Range violation
  ----------------
  ??:? _d_arrayboundsp [0x55b426ffabc1]
  ??:? _Dmain [0x55b426fe8f67]
  Process finished with exit code 1.
  ----------------

  hatası ile karşılaşılır...*/

Kodu, comment satırlarını açınca birbirilerini etkisizleştirecek şekilde tasarladım. Yani bu örnekte swap() ile assumeUnique() aynı anda olamaz. Olursa yukardaki hata ile karşılaşırsınız. Ama asıl çıktı ekranı aşağıdaki gibi olacaktır. İlk satır/dizi boş çünkü null oldu.:

>

[]
[immutable(S)(2, "iki"), immutable(S)(1, "bir")]

Kodu hata vermeye zorlarsanız (yani immutable bir dizinin elemanlarını yer değiştirirseniz) muhtemelen çıktı alamadan hata ile karşılaşacaksınız ki bu doğal. Aslında bu kadar tantanaya gerek yoktu çünkü basit bir cast() işlemi aslında.

Başarılar...

October 20, 2022

Niye exception modulunun içine koymuşlar acaba immutable yapmaklar exceptionların ne ilişkisi varki ?

Bir diziyi immutable yapmanın neye yarabileceğini düşündüm şöyle bir kaç fikir geldi aklıma,

1 - Kodun ve datanın güvenirliği, bir değişken belli bir zaman sonra hiç değişmemek gibi bir özelliğe sahip olabilir. Diyelimki bir kerede dosyadan okuduktan sonra hiç değişmeyen bir dizi. Bu dosya okuma işleminden sonra assumeUnique kullanıp kodumu daha güvenilir hala getirebilirim.

2 - Acaba immutable yaptığım diziyi derleme zamanında filan kullanabilirmiyim ama ilk başta değişken bir diziyi immutable yaptığı için benim bu düşüncem mantıksız sanki.

Galiba 2. kullanım örneğimi kendim çürüttüm ama 1. kullanım örneğim mantıklı mı?
Acaba benim düşünemediği gerçek hayatta başka kullanım örnekleri varmıdır?

Erdemdem

October 20, 2022
On 10/20/22 12:23, Erdem Demir wrote:
> Niye exception modulunun içine koymuşlar acaba immutable yapmaklar
> exceptionların ne ilişkisi varki ?

Haklısın. Mutlaka bir ucundan mantıklı bir açıklaması vardır. :)

> 1 - Kodun ve datanın güvenirliği, bir değişken belli bir zaman sonra hiç
> değişmemek gibi bir özelliğe sahip olabilir.

Aslında çok karşılaşılan bir kavramdır. Hatta bazı programlama dillerinde değişmezlik varsayılır ve değiştirilebilen değişkenler örneğin 'mut' diye tanımlanır (mutable'ın kısası).

> 2 - Acaba immutable yaptığım diziyi derleme zamanında filan
> kullanabilirmiyim

Kullanabilirsin.

> ama ilk başta değişken bir diziyi immutable yaptığı
> için benim bu düşüncem mantıksız sanki.

O assumeUnique'in kullanımıyla ilgili. 'immutable' başka yollarla da ilklenebilir:

// Derleme zamanında ilklenen bir dizi
immutable int[] kareler = hesapla(10);

// Derleme zamanında ilklendiğinin kanıtı
// (pragma(msg), derleme zamanında yazar.)
pragma(msg, kareler[3]);

// Bu işlevin derleme zamanından haberi bile yok
pure
int[] hesapla(int adet) {
    import std.range : array, iota;
    import std.algorithm : map;

    return iota(adet).map!(i => i * i).array;
}

void main() {
    // hesapla()'nın tanımındaki 'pure' silinirse
    // aşağıdaki satır derlenemez.
    immutable imm = hesapla(20);
}

> Acaba benim düşünemediği gerçek hayatta başka kullanım örnekleri varmıdır?

immutable'ın bir başka kullanımı, iş parçacıkları (thread) arasında kilit gerekmeden gönderilebilmesidir. (immutable veri, otomatik olarak 'shared'dir.)

Ali

October 21, 2022
On Thursday, 20 October 2022 at 19:48:30 UTC, Ali Çehreli wrote:
> On 10/20/22 12:23, Erdem Demir wrote:

> O assumeUnique'in kullanımıyla ilgili. 'immutable' başka yollarla da ilklenebilir:
>
> // Derleme zamanında ilklenen bir dizi
> immutable int[] kareler = hesapla(10);
>
> // Derleme zamanında ilklendiğinin kanıtı
> // (pragma(msg), derleme zamanında yazar.)
> pragma(msg, kareler[3]);
>
> // Bu işlevin derleme zamanından haberi bile yok
> pure
> int[] hesapla(int adet) {
>     import std.range : array, iota;
>     import std.algorithm : map;
>
>     return iota(adet).map!(i => i * i).array;
> }
>
> void main() {
>     // hesapla()'nın tanımındaki 'pure' silinirse
>     // aşağıdaki satır derlenemez.
>     immutable imm = hesapla(20);
> }
>
> > Acaba benim düşünemediği gerçek hayatta başka kullanım
> örnekleri varmıdır?
>
> immutable'ın bir başka kullanımı, iş parçacıkları (thread) arasında kilit gerekmeden gönderilebilmesidir. (immutable veri, otomatik olarak 'shared'dir.)
>
> Ali

Ali Abi ben assumeUnique()'in kullanimini merak ediyordum senin cevabin bir kismi biraz daha immutable degiskenlerin nerede kullanildiklari hakkinda olmus sanki ben guzel soramadim herhalde sorumu. Immutable degiskenlerin onemi ve kullanim yerleri konusunda hemfikirim fakat insan assumeUnique()' e niye ihtiyac duysunki gibi bir sorun belirdi kafamda.

Aklima gelen tek kullanimda belirli bir sure mutable olan bir degisken belli bir zaman veya olay sonrasi yasaminin geri kalaninda immutable olmasi oldu acaba varsayimim dogru mu diye sormak istedim.

Bu arada immutable verinin shared oldugunu bilmiyordum cok guzel birsey ogrendim tesekkur ederim.

Erdemdem
October 21, 2022
On 10/21/22 04:28, Erdem wrote:

> assumeUnique()' e niye ihtiyac duysunki gibi bir sorun belirdi kafamda.

Salih "kaynağı `null` yapıp bağını koparıyor" diye açıkladı diye düşünmüştüm.

> Aklima gelen tek kullanimda belirli bir sure mutable olan bir degisken
> belli bir zaman veya olay sonrasi yasaminin geri kalaninda immutable
> olmasi oldu acaba varsayimim dogru mu diye sormak istedim.

Aynı değişken immutable olamaz çünkü o değişkene başka bir yerden erişilip erişilmemekte olduğu ve o başka yer tarafından da immutable olacağı bilinemez ve belirlenemez. Tabii dinamik bir dilde belirlenebilir ama D gibi diller böyle "acaba artık immutable mı" diye bilgileri çalışma zamanında bilmeye çalışmazlar.

void foo() {
  int[] dizi = [ 1, 2 ];
  bar(dizi);  // Ya, bar() bir kenara bir referans koyduysa

  artıkImmutableOlsun(dizi);  // Böyle bir işlem olabilseydi
  // dizi[0] = 42; derlenemezdi; güzel...

  // Ama belki de elemanlar bar()'ın sakladığı referans yoluyla
  // değiştirebilirlerdi
  // ...
}

O yüzden, aynı değişkeni immutable yapamıyoruz ama onu "cast ederek" yeni bir değişken elde edebiliyoruz. Bu, zaten dilde var:

void main() {
    int[] dizi = [ 1, 2 ];

    auto değişmez = cast(immutable)dizi;

    // Bunlar derlenemez; güzel:
    // değişmez[0] = 42;
    // değişmez = [ 3, 4 ];

    // Ama bu, 'değişmez'i de değiştirir:
    dizi[0] = 43;
    assert(değişmez[0] == 43);
}

Ne oldu? Kendimizi kandırdık. assumeUnique biraz daha güvenli: Var olan bir diziyi immutable diye cast ediyor ama yanlışlıkla değiştiremeyelim diye var olan diziyi null yapıyor:

import std.exception : assumeUnique;

void main() {
    int[] dizi = [ 1, 2 ];

    auto değişmez = assumeUnique(dizi);

    // Bunlar derlenemez; güzel:
    // değişmez[0] = 42;
    // değişmez = [ 3, 4 ];

    // Artık bu da DERLENEMEZ:
    // dizi[0] = 43;
}

Bu basit kavramdan başka bir şey değil. :)

> Bu arada immutable verinin shared oldugunu bilmiyordum cok guzel birsey
> ogrendim tesekkur ederim.

Olaya bir de çöp toplayıcı karışınca veriler iki thread arasında immutable olarak geçerler ve kimse ne kiliklemek için performans düşürür ne de birbirine "işim bitti; artık bana verdiğin veriyi geri verebilirsin" diye mesaj göndermek zorunda kalmaz. Aslında çok büyük kolaylıktır ama bunları da D'ciler olarak pek satamıyoruz. :/

Ali

October 21, 2022
On 10/21/22 07:37, Ali Çehreli wrote:

>      // Artık bu da DERLENEMEZ:
>      // dizi[0] = 43;

Onu yanlış söyledim: Derlenebilir ama program çalışma zamanında hatayla sonlanır (segmentation fault?).

Ali