Thread overview
D Dilinin `Eval` ile İmtihanı
Jan 09
baykus871
Jan 09
baykus871
January 09
D'nin en çok **Metaprogramming** özelliğine bayılmış biri olaraktan bu dilde, yine benim Python'dan gelmişliğimin getirdiği 'eval'(evaluation) olmamasının farklılığı beni ilk önce pek rahatsız etmemişti.

Fakat sonradan anladım ki sadece derleme destekleyen dillerde böyle bir seçenek yok. Zaten olması da beklenemez. Çünkü derlenen bir dil ile ilgili bilgiler kod bilgileri olup yürütme zamanında elde edilmesi pekala söz konusu değildir.

Aksine **Evaluation** da yürütme zamanındaki kod üretmenin karşılığıdır. Yani 'Interpreting Language' dediğimiz dil sınıflarına aittir. D dili böyle bir dil değildir.
E.. hani bu kötü gibi görülebilir ama... bu fedakarlık hızının en büyük getirisi olmuştur.

Çünkü derlemek, kodu en iyi şekilde optimize edebilmeyi de gerektirir.
Bunu D Müthiş şekilde başarıyor.

Ancak Python gibi dillerin 'eval' seçeneği ile getirdiği esneklik, derleme-zamanı şablonlarının getirisini bildiğiniz aşıyor.

Niye mi?

O halde sorumun yanıtını, Python ve D bilenler(konuyu bilmek kafi) koduyla birlikte cevap versinler:
 -Soru:
    Kullanıcıdan girişte bir sayı listesi alın(Örnek: [1, 2, 3, 4...]) ve dört işlem için veyahut fazlası için gerekli operatörleri girişten alın(Örnek: ["+", "-", "*"...]). Sayı listesini ve operatörler listesini birbiri içine geçecek şekilde bir liste haline getirin(Örnek: [1, "+", 2, "/" ...]). En sonunda bu listedeki işlemleri tek tek yapacak bir işlev yazın ve o işlevin sonucunu kullanıcıya (STDOUT 'a) döndürün.
    İlk önce D dili ile böyle bir kod tasarlayın ve sonra Python (Kesinlikle 'eval' kullanın. Şiddetle tavsiye edilir.) ile bir de deneyin:

     Ne gördünüz? Fark nedir? => Benimle paylaşırsanız memnun olurum!

ASIL SORU: D'de 'eval'in gerektiği birçok yerde nasıl ergonomik bir çözüm kullanmalıyız?

???
January 08
Güzel anlatmışsın. :)

Baştan derlemenin eniyileştirmeye (optimization) ek başka bir yararı, kodun doğru olduğunun baştan denetlenebilmesi.

Eval'in olmamasına karşı başka bir çözümümüz daha var ama henüz tamamlanmadı: D derleyicisinin kütüphane olarak kullanılabilmesi. İşte o zaman istediğimiz dizgiyi alıp kod olarak derletip işletebileceğiz. Geçen aykı beerconf toplantısında kendisinden öğrendiğimize göre, bu projelerden birisi olan sdc'nin (stupid D compiler) yazarı deadalnix, tekrar üzerinde çalışmaya başlamış.

Ben bu konunun benzerini, dmd'yi çalışma zamanında işleterek ve ürettiği dinamik kütüphaneyi yükleyerek çözüyorum. Tabii benim durumumda bütün kodlar önceden yazılmış ve hatta tar'lanmış olarak programın içine gömülü. :) Yani, senin istediğin gibi serbestçe girilen kod derletmiyorum.

Senin verdiğin imtihanın çözümü genellikle "domain specific language" diyebileceğimiz biçimlerde çözülüyor. Örneğin, girişi ayrıştırıyoruz, '+', '-', vs. karakterlerin bildiklerimize uyduklarını görüp işlemi yine girişten dönüştürdüğümüz değerler üzerinde uyguluyoruz. Tabii Python'ın eval'ının yaptığı da bunun aynısı.

Sonuçta haklısın, bu iş böyle. :)

Ali


January 09
On Saturday, 9 January 2021 at 02:33:56 UTC, Ali Çehreli wrote:
> Güzel anlatmışsın. :)
>
> Baştan derlemenin eniyileştirmeye (optimization) ek başka bir yararı, kodun doğru olduğunun baştan denetlenebilmesi.
>
> [...]

Gayet doğru söylemişsiniz hocam. Böylelikle ben de bilgilerimi güncellerim.
Anca kanca beraber. Dilleri kıyaslaya kıyaslaya sözlük gibi olduk. Benim verdiğim imtihanın :D çözümü artık bu aşamada => "TO BE CONTINUED..."
January 14
On 1/8/21 6:09 PM, baykus871 wrote:

>   -Soru:
>      Kullanıcıdan girişte bir sayı listesi alın(Örnek: [1, 2, 3, 4...])
> ve dört işlem için veyahut fazlası için gerekli operatörleri girişten
> alın(Örnek: ["+", "-", "*"...]). Sayı listesini ve operatörler listesini
> birbiri içine geçecek şekilde bir liste haline getirin(Örnek: [1, "+",
> 2, "/" ...]). En sonunda bu listedeki işlemleri tek tek yapacak bir
> işlev yazın ve o işlevin sonucunu kullanıcıya (STDOUT 'a) döndürün.

İşlem önceliklerini gözardı ediyorum ve sırayla işletiyorum. Örneğin, "1 + 2 * 3"ün değeri 9 olacak, 7 değil.

Tabii ki Python'dan çok çok uzun çünkü aşağıda elle yaptığım işlemler Python'un eval'ının arkasında gizlenmiş olan işlemlerin aynıları. Bunun yerine code.dlang.org'da bulabileceğim bir kodu da kullanabilirdim: https://code.dlang.org/packages/arith-eval

import std.stdio;
import std.format;
import std.string;
import std.algorithm;
import std.exception;
import std.range;
import std.conv;

void main() {
  while (true) {
    try {
      işlet();
      writeln();

    } catch (Exception hata) {
      writefln!"HATA: %s"(hata.msg);
    }
  }
}

// Girişten sayılar ve işlemler okur ve işletir.
void işlet() {
  auto sayılar = elemanlarOku("Sayılar");
  enforce(sayılar.length >= 2, "En az iki sayı lütfen.");

  auto işlemler =
    elemanlarOku(format!"İşlem%s"(sayılar.length == 2 ? "" : "ler"));
  enforce(işlemler.length == sayılar.length - 1,
          "İşlem adedi sayı adedinden bir eksik olmalıdır.");

  auto sonuç = sayılar.elemanÇek.to!double;

  while (!işlemler.empty) {
    auto işlem = işlemler.elemanÇek;
    auto sayı = sayılar.elemanÇek.to!double;
    sonuç = hesapla(sonuç, işlem, sayı);
  }

  writefln!"Sonuç: %s"(sonuç);
}

// Girişten boşluk karakterleriyle ayrılmış olan elemanlar okur ve
// dizi olarak döndürür.
string[] elemanlarOku(string isim) {
  writef!"%s: "(isim);
  return readln.splitter.array;
}

// Aralığın ilk elemanını aralıktan çıkartır ve döndürür.
auto elemanÇek(R)(ref R aralık)
in (!aralık.empty) {
  auto eleman = aralık.front;
  aralık.popFront();
  return eleman;
}

auto hesapla(T)(T a, string işlem, T b) {
  switch (işlem) {
    static foreach (i; [ "+", "-", "*", "/" ]) {
      case i:
        enum ifade = format!"a %s b"(i);
        return mixin (ifade);
    }

      default:
        enforce(false, format!"Geçersiz işlem: %s"(işlem));
  }

  assert(false);
}

Ali