Thread overview
Bugün bir programlama tekniği geliştirdim!
Mar 21, 2013
Salih Dinçer
Mar 21, 2013
Salih Dinçer
March 21, 2013

Basit bir şey aslında...:)

Enum'lar ile bu kadar çok içli dışlı olunca; açıklamlarını bölerek yapacağım şu örnekteki tekniği geliştirdim. Aslında bir süredir isimsiz enum'lar ile yazılımın en başına oluşturduğum bu kümede, bir çok sabite yer veriyordum. Örneğin yazılımın ismi, test süreçlerinde kullanılacak parametreler vb. bir çok öğe (hesap&kitap) burada bulunuyordu...

Şimdi ise bunu, tür şablonunu kullanarak sınıf aktarmayı denedim. Pekala güzelce çalışıyor:

import std.stdio;
import std.traits;

class BirSınıf(E)
 if( is(E == enum) ) {

 static assert(isUnsigned!E, "\n\tKULLANILMASI GEREKENLER:\n"
                             "\tubyte, ushort, uint, ulong\n");
 BirYapı[] kütük;
 string kütükAdı;
 string sınıfAdı;

 this(string kütük, string sınıf) {
   this.kütük = new BirYapı[](E.adet);
   this.kütükAdı = kütük;
   this.sınıfAdı = sınıf;
 }

 void ekle(size_t nm, string ad) {
   this.kütük[nm].numarası = E.numBaş + nm;
   this.kütük[nm].adı = ad;
   this.kütük[nm].sınıfı = this.sınıfAdı;
 }

 override string toString() const  {
   string lines = std.array.replicate("=", 30);
   string çıktı = kütükAdı ~ " - " ~
                  sınıfAdı ~ " öğrencileri:\n";
   çıktı ~= lines ~ "\n";

   if(E.test) return format("%(%s\n%)", kütük);
   else foreach(i, öğrenci; kütük) {
     if(i%E.xSütun == 0 && i != 0) çıktı ~= "\n";
     çıktı ~= format("(%d) %s\t", öğrenci.numarası,
                                  öğrenci.adı);
   }
   return çıktı ~ "\n"  ~ lines;
 }
}

struct BirYapı {
 size_t numarası;
 string adı;
 string sınıfı;
}
 /* Statik(belirli) bir veri kaynağından,
  * 4 öğrenci ismi geleceğini düşünelim:
  */
 string[4] öğrencilerim;

void main() {
/*************** LİSTELEME PARAMETRELERİ ***************/
 enum p1 : size_t {
   //test = 1,/*
   test,//* ^-- Programcı görünümü için aç */
   adet   = öğrencilerim.length,
   numBaş = 100,
   xSütun = 2
 }
/*************** LİSTELEME PARAMETRELERİ ***************/

 öğrencilerim = [ "Ahmet", "Ali", "Ayşe", "Azra" ];

 /* Bu veriler ODTÜ öğrencilerinin, FEN1B sınıfının
  * isimleri olduğunu işlevsel sınıfımıza bildirelim:
  */
 auto FEN1B = new BirSınıf!p1("ODTÜ", "FEN1B");
 /* DİKKAT:
  * Biz listeme parametreleri (p1) sayesinde, gereksiz yere
  * kütük açmadan veri uzunluğunu da bildirmiş olduk!
  */

 foreach(i, öğrenci; öğrencilerim) {
   FEN1B.ekle(i, öğrenci);
   öğrenci.write(", eklendi...");
 }
 "\n".writeln;
 FEN1B.writeln;
} /*Çıktısı:
Ahmet eklendi...Ali eklendi...Ayşe eklendi...Azra eklendi...

ODTÜ - FEN1B öğrencileri:
==============================
(100) Ahmet      (101) Ali
(102) Ayşe       (103) Azra
==============================
*/

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 21, 2013

Şimdi, gelelim fasülyenin faydalarına...:)

Elbette sınıfın işleyişini etkileyebilecek bir çok parametreyi this()'de kurarken verebilirdik. Ama bunlar birer değişken olurdu ve içeride bir hükümlerinin olabilmesi için bir üye tarafından temsil edilmeleri gerekirdi. Bu bir...

Pekala, verinin uzunluğu gibi şeyleri sınıf içerisinde array.length ve dinamik dizi kullanarak halledebilirdik. Bu örnek tamamen bir hayal ürünü ve belki daha işe yarar olabilirdi. Ama otomatik öğrenci numaralarının belirlenmesi (bu 2), ekrana gelen listedeki sütun sayısı (bu 3) ve geliştirici için test çıktısı (bu 4) gibi bir çok nitelik bence işe yarar olduğunu gösteriyor.

Aslında sınıfta bu özelliği kullanmak, E harfini parantez içinde ve sınıf ismi yanında kullanmak kadar basit:

Alıntı:

>
> class BirSınıf(E) {
>   BirYapı[] kütük;
>   string kütükAdı;
>   string sınıfAdı;
>
>   this(string kütük, string sınıf) {
>   :  :  :
> ```

>

Yani yukarıdaki gibi hemen kullanmaya başlayabliirdik. Çünkü biz sınıfa gelen bu tür şablonunu ne amaçla kullanacağımızı biliyoruz. Zaten "E.{sabit_ismi}" şeklinde basit bir kullanımı var. Ancak, yabancı birinin buraya enum olmayan bir tür göndermesi ve/veya işaretli olup ciddi hatalara sebebiyet vermesini istemezsek önceki gibi de kullabilirsiniz.

Bu sınıfın ayrıca 2 üye işlevi var ve her ikisinde de E şablonu kullanılmakta:

Alıntı:
>
>
>
void ekle(size_t nm, string ad)

override string toString() const
>

Kulanılan parametreler ise herhangi bir yerde olabilir. Bir tek sınıfı kurduğunuz yerde ulaşılabilir olması yeterli. Yani derleyici, sınıfın görmesini bizden aramıyor ve derlerken tüm değerler yerlerine yerleştiriliyor. Dilersek p1, p2, p2 ... şeklinde sonsuza kadar giden parametre kümelerimiz olabileceği gibi bunu aşağıda istediğiniz yerini değiştirerek de yapabiliriz:

Alıntı:

>
>   enum p1 : size_t {
>     //test = 1,/*
>     test,//* ^-- Programcı görünümü için aç */
>     adet   = öğrencilerim.length,
>     numBaş = 100,
>     xSütun = 2
>   }
> ```

>

Meğer bu enum'lar o kadar güzel şeylermiş ki, bir önceki satırda tanımlanan sabiti hemen bir altta da kullanabiliyorsunuz. Dolayısıyla karmaşık bir hesaplama yapılıyorken sık sık bir enum kümesine başvuruyorum. Bu isterse isimsiz olsun, gerçekten çok prartik.

Hele bu sabitleri, sınıf kurulurken bir ünlem işareti ile gönderebilmemiz ise muhteşem, değil mi?

Alıntı:
>
>
>

auto deneme = new BirSınıf!p1();

>

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 21, 2013

Güzel. Hiç böyle kullanıldığını görmemiştim. Temiz görünüyor. :)

Aslında geçen gün baktığımız Mersenne Twister Engine'de de gördüğümüz ayrı değerleri tek enum içinde almış oluyorsun.

Açıkça verseydin okunaklı olması için yeni bir isim vermek de gerekirdi:

alias MersenneTwisterEngine!(uint, 32, 624, 397, 31, 0x9908b0df, 11, 7,
                            0x9d2c5680, 15, 0xefc60000, 18)
   Mt19937;

Seninki bu işi daha temiz hallediyor ama bütün değerlerin birbileriyle uyumlu olmalarını gerektiriyorsun. Ayrık olduğunda ise araya string gibi başka türler de karıştırabiliriz.

Alıntı (Salih Dinçer):

>

Elbette sınıfın işleyişini etkileyebilecek bir çok parametreyi this()'de kurarken verebilirdik.

Ben onu C kütüphanelerinde gördüm. Nesneyi kuran işlev Parametreler gibisinden başka bir nesne göstergesi alır. Seninkiyle aynı mantık ama C'de şablon olmadığı için başka yolu yok.

Alıntı:

>

Ama bunlar birer değişken olurdu ve içeride bir hükümlerinin olabilmesi için bir üye tarafından temsil edilmeleri gerekirdi.

Bazıları için doğru ama eğer bazılarını yalnızca kurucu içinde sabit değer olarak kullanacaksak üye olmaları gerekmez. Ama genelde haklısın.

Burada şablonların bir özelliği aklıma geliyor. (Bu, MersenneTwisterEngine'i de etkiliyor.) Şablonlar her şablon parametresi için farklı tür haline gelirler. BirSınıf!p1 ve BirSınıf!p2 nesneleri aynı türden olmazlar.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]