Thread overview
std.traits ile yapılabilir mi?
June 07

Merhaba hocam,

Çok basit bir soru ama yapamadımz mazur gör lütfen:

void main() {
  string bar;
  void foo(S)(S s)
  in(is(S == S)) {           // (in)
    bar ~= s;
  }
  foo('-');
  foo(" -");
  assert(bar == "- -");
  foo('\n');
  foo(" v");
  assert(bar == "- -\n v");
  foo(41);                   // (41)
  assert(bar == "- -\n v)");
}

Acaba std.traits kullanarak (in) bloğunda (41) satırı engellenebilir mi?

Çünkü foo'nun sadece char ve türevlerini hem birden fazla char hem tek almasını istiyorum da...

Teşekkürler...

June 07
On 6/7/22 12:07, Salih Dincer wrote:

>    void foo(S)(S s)
>    in(is(S == S)) {           // (in)
>      bar ~= s;
>    }

in, çalışma zamanında işletilen sözleşmeli programlama olanağıdır. Sen burada şablon kısıtlaması olan if'i düşünmüşsün:

import std.traits;

void main() {
  string bar;
  void foo(S)(S s)
  if(isSomeString!S ||
     isSomeChar!S) {           // (in)
    bar ~= s;
  }

[...]

Ali

June 08

On Tuesday, 7 June 2022 at 19:16:37 UTC, Ali Çehreli wrote:

>

in, çalışma zamanında işletilen sözleşmeli programlama olanağıdır. Sen burada şablon kısıtlaması olan if'i düşünmüşsün:

Aslında in bloğunu kullanabilmek isterdim çünkü bu benim için çok daha kolay. Yani hata mesajı vermesini tercih ederdim. Tamam, zaten 2 satıra yönelik bir hata mesajı veriyor:

>

Error: template D main.foo cannot deduce function from argument types !()(int), candidates are:

>

source.main.foo(S)(S s) if (isSomeString!S || isSomeChar!S)

Deneyimli bir programcı için bunlar yeterli ve fakat herkes için en kolayı kendi dilinde bir hata atmasıdır. Çünkü program büyüdükçe nesneler arasındaki ilişki artıyor. Çıkan satırlar dolusu hata içinden birine odaklanabilse tüm hatalar otomatik düzelecek.

Steve Schveighoffer'ın makalesini okumaya karar verdim. Belki hatalar ile mücadele etme konusunda vakit kazandırıcı önerileri vardır.

Şimdilik her yerde kullanılabilen şöyle bir ekstra işlev ile istediğimi elde etmiş görünüyorum:

bool char_ise(S)() {
  import std.traits;
  if(isSomeString!S || isSomeChar!S) {
    return true;
  } else throw new Exception("Sadece char!");
  return false;
}

void main()
{
  string bar;

  void foo(S)(S s)
  if(char_ise!S())/*
  if(isSomeString!S || isSomeChar!S)//*/
  {
    bar ~= s;
  }
//  ....

Tabi çok aptalca lüzumsuz bir kullanım, tek satır varken. En azından, verdiği hata mesajından CTFE çalıştığını anlıyoruz:

false olma durumunda ekstra verdiği hatalar:

>

Error: uncaught CTFE exception object.Exception("Sadece char!")
called from here: char_ise()

Teşekkürler...

June 07
On 6/7/22 22:19, Salih Dincer wrote:
> On Tuesday, 7 June 2022 at 19:16:37 UTC, Ali Çehreli wrote:
>>
>> in, çalışma zamanında işletilen sözleşmeli programlama olanağıdır. Sen
>> burada şablon kısıtlaması olan if'i düşünmüşsün:
>>
>
> Aslında `in bloğu`nu kullanabilmek isterdim çünkü bu benim için çok daha
> kolay. Yani hata mesajı vermesini tercih ederdim. Tamam, zaten 2 satıra
> yönelik bir hata mesajı veriyor:
>
>> Error: template `D main.foo` cannot deduce function from argument
>> types `!()(int)`, candidates are:
>
>> `source.main.foo(S)(S s) if (isSomeString!S || isSomeChar!S)`
>
> Deneyimli bir programcı için bunlar yeterli ve fakat herkes için en
> kolayı kendi dilinde bir hata atmasıdır.

Kendi dilinden önce bir konu var: Kod derlenemesin bile mi yoksa derlensin de çalışma zamanında mı hata atsın? Derleme zamanı tercih edilir.

> Şimdilik her yerde kullanılabilen şöyle bir ekstra işlev ile istediğimi
> elde etmiş görünüyorum:
>
> ```d
> bool char_ise(S)() {
>    import std.traits;
>    if(isSomeString!S || isSomeChar!S) {

Tekrar ediyorum ama eğer derlenemesin istiyorsak 'static if' olmalı.

>      return true;
>    } else throw new Exception("Sadece char!");

Eğer 'static if' olacaksa o da 'static assert' olmalı.

Şu nasıl?

bool char_olmalı(S)() {
  import std.traits;
  static assert(isSomeString!S || isSomeChar!S,
                "Sadece char!");
  return true;
}

void main()
{
  string bar;

  void foo(S)(S s)
  if (char_olmalı!S()) {
      bar ~= s;
  }

  foo(42);
}

Ben 'if' ile kullandım ama 'in' ile de çalışsın diye senin yaptığın gibi 'true' döndürecek biçimde bıraktım.

Ali

June 08

On Wednesday, 8 June 2022 at 06:44:00 UTC, Ali Çehreli wrote:

>

[...]
Ben 'if' ile kullandım ama 'in' ile de çalışsın diye senin yaptığın gibi 'true' döndürecek biçimde bıraktım.

Derleme zamanı verdiği hata, kapsamlı bir uygulama için bence de gereksiz kaçıyor. Bu tür olanakları ile arkadaş olmaya çalıştıkça sistemin işleyişini daha iyi anlıyorum ki düne kadar çoğunlukla assert() kullanan biri olarak söylüyorum, teşekkürler...

void main()
{
  string bar;
  enum Err { ch = "Sadece char!" }

  void foo(S)(S s)
  in(isSomeString!S || isSomeChar!S, Err.ch)/*
  in(char_ise!S())//*/
  {
  // ....

Çalışma Zamanı Hataları

  • isSome...'lar in bloğundayken:
>

core.exception.AssertError@ins.d(70): Sadece char!

  • isSome...'lar char_ise'deyken:
>

object.Exception@ins.d(53): Sadece char!

Dediğim gibi in bloğu kullanabilmek önemliydi ve görünüşe göre işin içine static girince, derleme zamanında da hata yakalamak mümkünmüş:

in bloğunda char_olmalı!S() kullanılırsa

>

ins.d(59): Error: static assert: "Sadece char!"
ins.d(71): instantiated from here: char_olmalı!int
ins.d(81): instantiated from here: foo!int

Başarılar...

June 08

On Wednesday, 8 June 2022 at 07:32:14 UTC, Salih Dincer wrote:

>

std.traits inceleyin:

  1. https://dlang.org/spec/traits.html
  2. https://dlang.org/phobos/std_traits.html#isSomeString

D'ye gönül vermiş herkes lütfen 2. maddedeki web sayfasını incelesin. Çünkü orası diğerine göre daha kapsamlı (örnekli) anlatmış. Özellikle isSomeString için şöyle bir örnek var:

static struct Stringish
{
    string str;
    alias str this;
}
static assert(!isSomeString!Stringish);

Bu string gibi görünenleri geçirmediğini ifade ediyor. Çünkü bu bir yapı sarmalı ama standart işlev veya opCall() üzerinden string geçerse itiraz yok. Öyle ya tam bir string döndürüyor! Şöyle opCall() uygulamalı kapsamlı bir örnek yaptım, şahane çalışıyor:

string bar = "_character() {"; // TEST İÇİN

bool string_mi(S)() {
  import std.traits;
  enum Err { ch1 = "Sadece char!" }
  static assert(isSomeString!S ||
                isSomeChar!S, Err.ch1);
  return true;
}

void foo(S)(S s) in(string_mi!S()) {
    bar ~= s;
}

static struct SonEk {
    string ek;

    this(string str) {
      this.ek = str;
    }
    string opCall(bool lf) {
      if(lf) ek ~='\n';
      return ek;
    }
}

void main()
{
  import std.stdio;
  auto test = SonEk("}");
  test(true).foo();
  //foo(true); // derleme hatası
  //foo(1); // derleme hatası
  //foo(1.1); // derleme hatası
  bar.writeln("-SATIR SONU-");
}
**ÇIKTISI:**
> _character() {}
> -SATIR SONU-
> Compilation finished successfully.

Başarılar...
June 08
On 6/8/22 06:42, Salih Dincer wrote:

>    enum Err { ch1 = "Sadece char!" }

Aynı hatayı başka bir konuşma dilinde de verebilmek için mi öyle ayrı yazıyorsun?

Hata mesajlarının farklı dilde yazdırılması konusu arada sırada gündeme gelir. Bu koduda Walter'ın hep anlattığı bir şey: Başka bir derleyicisinde ısrarlar üzerine dil seçeneği sunmuş ve sonra kimsenin o olanağı kullanmadığını farketmiş.

> void foo(S)(S s) in(string_mi!S()) {
>      bar ~= s;
> }

Senin orada neden 'in' kullandığını konuştuk ama bunu gören başka arkadaşlar yanlış öğrenmesinler diye, 'in'in sözleşmeli programlama olanağı olduğunu ve normalde çalışma zamanında işletilmek için tasarlandığını hatırlatıyorum.

Bir şablonun ancak belirli bir tür için kullanılabildiğini normalde şablon kısıtlaması olan 'if' ile gösteriyoruz.

> static struct SonEk {

Onu ben de bazen yapıyorum ama 'static'in o kullanımının modül düzeyinde bir etkisi yoktur.

Ali

June 09

On Wednesday, 8 June 2022 at 16:17:43 UTC, Ali Çehreli wrote:

>

On 6/8/22 06:42, Salih Dincer wrote:

>
enum Err { ch1 = "Sadece char!" }

Aynı hatayı başka bir konuşma dilinde de verebilmek için mi öyle ayrı yazıyorsun?

Hayır, bütün hataları Err isminde bir enum altında toparlamak için yazıyorum. Belki programlama tekniği açısından yanlış yapıyor olabilirim. Çünkü koda tekrar dönüp baktığımda, örneğin "ch1 de neymiş" diyeceğim. Gerçi kodu okumasını bilen "hata1" deyip geçiştirmek bile sorun değil.

Bir başka amacım ise belgelendirme ile vakit kaybetmemek. Yani kısaca, "stack boş", "length uzadı", "geçersiz unicode" vb. deyip geçtim. Kendimi kodu yazmaya odaklıyorum, text'leri enum'lara itekledim (teşbihte hata olmaz 😀) ve arada TO-DO comment atıyorum.

On Wednesday, 8 June 2022 at 16:17:43 UTC, Ali Çehreli wrote:

>

Hata mesajlarının farklı dilde yazdırılması konusu arada sırada gündeme gelir. Bu koduda Walter'ın hep anlattığı bir şey: Başka bir derleyicisinde ısrarlar üzerine dil seçeneği sunmuş ve sonra kimsenin o olanağı kullanmadığını farketmiş.

Bunu bilmiyordum hocam, bilgi için teşekkürler. Arada kod yazma teknikleri, kolaylıkları açısından önerilerde bulunursanız, inanın çok feyzleniyoruz. Örneğin
şu TO-DO yazıp daha sonra bakma olayına kendimi alıştırdım. DITTO nedir onu anlamıyorum gerçi sözlükten baksam bulurum da. Başka neler var?

On Wednesday, 8 June 2022 at 16:17:43 UTC, Ali Çehreli wrote:

>

On 6/8/22 06:42, Salih Dincer wrote:

>
void foo(S)(S s) in(string_mi!S()) {
     bar ~= s;
}

Senin orada neden 'in' kullandığını konuştuk ama bunu gören başka arkadaşlar yanlış öğrenmesinler diye, 'in'in sözleşmeli programlama olanağı olduğunu ve normalde çalışma zamanında işletilmek için tasarlandığını hatırlatıyorum.

Örneğin bunu "stack boş" hatası için kullandım. Burada tartıştığımız isSome... olanaklarını test etmek içindi. Asıl kodda ne static var, ne de modüller arası string...

On Wednesday, 8 June 2022 at 16:17:43 UTC, Ali Çehreli wrote:

>

On 6/8/22 06:42, Salih Dincer wrote:

>
static struct SonEk {

Onu ben de bazen yapıyorum ama 'static'in o kullanımının modül düzeyinde bir etkisi yoktur.

Bunu anlamadım hocam ama zaten ne SonEk diye bir şey var ne de static bir yapı. Static öğeleri dikkatli kullanmaya çslışıyorum. Sizin SpellOut'u yazarken hızlı olması ve bellekte tek bir bölgeyi kullanmak için static buffer kullandığınızı hatırlıyorum.

Merak edenler olursa SONY-1: Short Scale Numbers başlığına bakabilir.

Şimdi aklıma geldi de yeni bir "Siz Olsanız Nasıl Yapardınız" meydan okumadının vakti gelmiş. Ama henüz aklıma bir şey gelmiyor...😀

Saygılar...

June 08
On 6/8/22 17:21, Salih Dincer wrote:

> Belki programlama tekniği açısından yanlış yapıyor
> olabilirim.

Ben ilk zamanlarımda öyle düşünmüştüm ama daha sonradan, verilen hata mesajının hangi satırda olduğunu hemen görüvermenin daha yararlı olduğunu anladım. "merhaba" gibi bir dizgi sabitinin "sihirli sabit" dediğimiz 42 gibi değerlerden farklı olmadığın ve o yüzden yanlış olduğunu düşünüyordum ama "merhaba"ya 'selam' vs. gibi bir sembolik isim vermek aslında hiç ek yarar sağlamıyor. Nadir durumlarda işe yarayabilir ama bir dizgiyi tam da kullanıldığı yere yazmak çok daha yararlı.n

> DITTO nedir onu anlamıyorum gerçi sözlükten baksam bulurum

"Aynısı" veya "aynısı bunun için de geçerli" demek.

> Başka neler var?

Pek başka bir şey yok. Bazen XXX ("bunu merge etmemeliyiz" gibi geçici kod için), HACK ("evet, burada kötü bir şey yapıyoruz belki ileride düzeltiriz"), vs.

>> Onu ben de bazen yapıyorum ama 'static'in o kullanımının modül
>> düzeyinde bir etkisi yoktur.
>
> Bunu anlamadım hocam

Yani, modül düzeyinde aşağıdaki 'static'ler kaldırılabilir ve kodda hiçbir değişiklik olmaz:

static int i;
static struct S {}
// vs.

> hızlı olması ve bellekte tek bir bölgeyi kullanmak
> için static buffer kullandığınızı hatırlıyorum.

O, bir işlev içindeydi. Yukarıda söylediğim, modül düzeyindeki tanımlar için...

Ali