Thread overview
Is yerinde kucuk bir D programi
September 07
Blender'da yaptigim basit objeleri C++ koduna almam gerekiyordu.

Blender'da olusturdugum.obj dosyasinin icerigi "string input" degiskeninde gorulebilir.



```
import std; // --> Bunu Ali abiden yeni ogrendim guzel bir ozellik

string input = "o Plane_Plane.001
v -1.000000 -1.000000 0.000000
v -0.061671 -0.947391 0.000000
v -0.037190 -0.087611 0.000000
v 0.000000 -1.000000 0.000000
v -0.894849 -0.945749 0.000000
v -1.000000 -0.997879 0.000000
v 0.000000 0.000000 0.000000
v -0.061671 -0.947391 0.000000
v -0.560963 -0.611677 0.000000
v -0.573407 -0.624128 0.000000
s off
f 4 8 5
f 9 3 7
f 10 2 9
f 6 1 5
f 1 4 5
f 4 7 3
f 8 2 5
f 4 3 8
f 7 6 9
f 6 5 10
f 9 6 10";

void main()
{
   writeln(input.
               split('\n').
               filter!( a => a.startsWith("v")).
               map!(a => a[2..$].replace(" ", ",")).
               map!(a => "{" ~ a ~ "}," ).
               join("\n"));
}

```


Bu "one liner" obj formatindan vertex'leri alip C+ dizisinin anlayabilecegi formata donusturuyor ve beni mutlu ediyor.

erdem@erdem-HP-EliteDesk-800-G2-TWR ~/dev/DScripts $ dub run
Performing "debug" build using dmd for x86_64.
dscripts ~master: building configuration "application"...
Linking...
Running ./dscripts
{-1.000000,-1.000000,0.000000},
{-0.061671,-0.947391,0.000000},
{-0.037190,-0.087611,0.000000},
{0.000000,-1.000000,0.000000},
{-0.894849,-0.945749,0.000000},
{-1.000000,-0.997879,0.000000},
{0.000000,0.000000,0.000000},
{-0.061671,-0.947391,0.000000},
{-0.560963,-0.611677,0.000000},
{-0.573407,-0.624128,0.000000},


Kucuk bir sey olsa bile isyerinde kullandigim icin paylasmak istedim.
-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
September 07
Ya ben bu D yi cok seviyorum bazen ,

Simdi bu basit objeleri alirken C++ projende istedigim gibi cizilmiyordu blenderdan farkli ucube sekiller cikiyordu. Sonra farkettim ki obj. formati "face" leri 1 'den baslatiyormus. Ama C++ dizileri 0 'dan basliyor.

yani

f 4 8 5 = 3,7,4 olarak degistirilmeli

bunu yaklasik 30 saniyede cozmeyi basardim elimle yapayim deseydim yanmmistim ugras dur..

Su butun olayi cozdu

   writeln(input.
           split('\n'). // Her bir elemena icin (ben sadece f 4 8 5 satirini ornekleyecegim aciklamalarda)
           filter!( a => a.startsWith("f")).  // f 4 8 5
           map!(a => a[2..$].replace(" ", ",")). // 4,8,5
           map!(a => a.split(",").map!( a=> to!string(to!int(a)-1)).join(",")). // 3,7,4 // Bu adim 1 dusurdugum kritik adim
           map!(a => "{" ~ a ~ "}," ). // {3,7,4}
           join("\n")); {3,7,4},{8,2,7}....
-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
September 07
Benim seviyemde birinin bile bu kodu abartmiyorum 2 dakika da yazmasi D nin guzelligi gercekten.

Ilk basta usenmistim elle 3-5 kere yaptim ayni seyi ama D kodunu yazmanin bu kadar kisa olacagini tahmin etmemistim.

Objelerimde gittikce karmasiklasicak ve daha cok vertex ve daha cok face olacak. Ama artik bir sorun teskil etmiyor cunku herseyi bu scriptimsi program yapacak. Cok mutluyum suan :)

Erdemdem
-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
September 07
Kodun son hali :

```
import std;

string input = "v -1.000000 -1.000000 0.000000
v 0.000000 -1.000000 0.000000
v 0.000000 0.000000 0.000000
v -0.764302 -0.902371 0.000000
v -0.092399 -0.907601 0.000000
v -0.098275 -0.237258 0.000000
v -0.477832 -0.902371 0.000000
v -0.098275 -0.521522 0.000000
v -0.382539 -0.521522 0.000000
v -0.135045 -0.576491 0.000000
v -0.070175 -0.169419 0.000000
v -0.477832 -0.615901 0.000000
v -0.423509 -0.576491 0.000000
v -0.830581 -0.929825 0.000000
v -0.423509 -0.864955 0.000000
v -0.450378 -0.549622 0.000000
v -0.092399 -0.603273 0.000000
v -0.396727 -0.907601 0.000000
v -0.450378 -0.929825 0.000000
v -0.070175 -0.929825 0.000000
v -0.070175 -0.549622 0.000000
s off
f 19 1 2
f 21 2 3
f 16 3 1
f 6 21 11
f 6 16 9
f 9 21 8
f 4 16 14
f 4 19 7
f 12 19 16
f 10 16 13
f 15 16 19
f 10 19 21
f 18 20 5
f 17 20 21
f 18 21 19
f 2 20 19
f 19 14 1
f 3 11 21
f 21 20 2
f 1 14 16
f 16 11 3
f 6 8 21
f 6 11 16
f 9 16 21
f 4 12 16
f 4 14 19
f 12 7 19
f 10 21 16
f 15 13 16
f 10 15 19
f 18 19 20
f 17 5 20
f 18 17 21
";


void main()
{
   writeln("Vertexes : " );
   writeln(input.
               split('\n').
               filter!( a => a.startsWith("v")).
               map!(a => a[2..$].replace(" ", ",")).
               map!(a => "{" ~ a ~ "}," ).
               join("\n"));

   writeln("Faces : " );
   writeln(input.
           split('\n').
           filter!( a => a.startsWith("f")).
           map!(a => a[2..$].replace(" ", ",")).
           map!(a => a.split(",").map!( a=> to!string(to!int(a)-1)).join(",")).
           map!(a => "{" ~ a ~ "}," ).
           join("\n"));
}

```


Ve ciktisi :

Vertexes :
{0.000000,-1.000000,-0.000000},
{-1.000000,-1.000000,0.000000},
{-1.000000,0.000000,0.000000},
{-0.221739,-0.908153,-0.000000},
{-0.908362,-0.908362,0.000000},
{-0.906714,-0.225213,0.000000},
{-0.517570,-0.908153,0.000000},
{-0.906714,-0.516131,0.000000},
{-0.517570,-0.612322,0.000000},
{-0.615796,-0.516131,0.000000},
{-0.154739,-0.935905,-0.000000},
{-0.584104,-0.842277,0.000000},
{-0.842277,-0.584104,0.000000},
{-0.935905,-0.154739,0.000000},
{-0.584104,-0.584104,0.000000},
{-0.545322,-0.545322,0.000000},
{-0.908362,-0.611817,0.000000},
{-0.611817,-0.908362,0.000000},
{-0.545322,-0.935905,0.000000},
{-0.935905,-0.935905,0.000000},
{-0.935905,-0.545322,0.000000},
Faces :
{0,10,18},
{1,19,20},
{2,13,15},
{10,8,3},
{18,3,6},
{8,18,6},
{5,20,7},
{9,13,5},
{20,9,7},
{15,12,14},
{11,15,14},
{12,18,11},
{19,17,4},
{16,19,4},
{18,16,17},
{18,19,1},
{1,0,18},
{20,13,2},
{2,1,20},
{15,10,0},
{0,2,15},
{10,15,8},
{18,10,3},
{8,15,18},
{5,13,20},
{9,15,13},
{20,15,9},
{15,20,12},
{11,18,15},
{12,20,18},
{19,18,17},
{16,20,19},
{18,20,16},


Bana kalan bunlari copy-paste yapmak C++ projesine
-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
September 07
Is yerindeki arkadaslara D'yi tanitiyodum dun bakin 2 dakkada isimi halledicek bir sey yapabiliyorum filan diye. Arkadaslardan biride kod tekrari var demisti. Bende hak vermistim senin kodunu gosterecem bugun.


formattedWrite'i okumam gerekiyor anlamam icin biraz karisik gozukuyor. Ama anladiktan sonra cok guclu bir alet gibi gozukuyor. Benim 2 map ile yaptigim seyi cozmus tek basina.

Ali Abi ben bu ornekte tembel calisan algoritmalarin nasil fayda saglayacagini anlamadim cunku daha ilk adimda filter ile ise yaramayanlari zaten eliyorum. Sonra elimde kalanlarin hepsini zaten dolasmam gerekiyor. Burda ben bir noktayi atliyorum cogu ihtimalle atladigim noktayi belirtebilirmisin tembellik konusunda?

Erdemdem
-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
September 07
Katılıyorum! Ama... :)

İlgimi çekti ve senin harcadığından çok fazla zaman harcayarak daha da güzelleştirmeye çalıştım. Programının senin işini gördüğünü biliyorum ama eğer veri buradakinden çok daha büyük boyutlara erişirse daha hızlı bir şey bulabiliriz.

Senin kodda ilk dikkatimi çekenler şunlar oldu:

* ~ işleci yavaştır çünkü hep yeni bir dizi üretir
* Hevesli (eager) olan split(), tembel olan splitter()'dan daha yavaştır
* Hevesli olan join(), tembel olan joiner()'dan daha yavaştır
* to!string bellek ayıracağından çıkışa verene kadar dönüşümden kaçınmak gerekir.
* Kod tekrarları var

dmd'nin -profile=gc seçeneğine güvenimizi yitirmiş gibi olsak da dmd 2.093.1 ile denedim ve senin programın için şu sonucu gördüm
'
bytes allocated, allocations, type, function, file:line
          1120	             35	std.array.Appender!(string[]).Appender.Data std.array.Appender!(string[]).Appender.this /usr/include/dmd/phobos/std/array.d:3249
           672	             21	immutable(char)[] deneme.main.__lambda3 deneme.d:1643
           528	             33	immutable(char)[] deneme.main.__lambda7 deneme.d:1652
'

Bu kadar küçük veri için toplam 2K'nın biraz üzerinde ve yaklaşık 100 kere bellek ayrılmış. Aşağıdaki program ise sanırım hiç bellek ayırmıyor çünkü profilegc.log dosyasına yazılmıyor bile. Bence de öyle çünkü programda bellek ayrılan bir yer göremiyorum.

```
/*
 Burada 'beg'in şablon parametresi olarak verilmesinin neden gerektiğini anlamıyorum.
*/
auto parse(string beg, R)(R range)
if (isSomeString!(ElementType!R))
{
 return range.
        filter!(a => a.startsWith(beg)).
        map!(a => a[2..$].splitter(' '));
}

auto print(R)(string label, R range)
if (isInputRange!R &&
   isInputRange!(ElementType!R))
{
 /*
   Sonuçları bu işlevde yazdırıyorum ama bunu hiç bellek ayırmadan hallediyoruz. :)

   stdout.lockingTextWriter bir çıkış aralığıdır (put() işlemini destekler). formattedWrite() da çıkış aralıklarıyla
   çalışırken karakterleri hiç dizgi üretmeden doğrudan o çıkış aralığına gönderir.

   Burada R bir "aralık aralığı" olduğundan iç içe iki "eleman düzeni" belirteci kullanıyorum ("%(" ve "%)"). Bu
   belirteçler baştan karmaşık görünebiliyorlar ama bir kere anlayınca çok işe yarıyorlar:

     http://ddili.org/ders/d/cikti_duzeni.html#ix_cikti_duzeni.%(
  */
 stdout.lockingTextWriter.
   formattedWrite!"%s : \n%-({%-(%s,%)},\n%|%)"(label, range);
}

void main()
{
 auto lines = input.splitter('\n');

 print("Vertexes", lines.parse!"v");
 print("Faces", lines.parse!"f".
                map!(a => a.map!(a => a.to!int - 1)));
}
```

Ali
-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
September 08
Alıntı (kerdemdemir):
>
> formattedWrite'i okumam gerekiyor anlamam icin biraz karisik gozukuyor.

Burada iki tane iç içe kullandığım için gerçekten karışık ama en basit olarak şu anlama geliyor: "%( ve %) arasındaki belirteci aralığın bütün elemanlarına uygula". Neyin elemanlar arasında ayraç olarak kullanılacağına kendisi akıl yürütüyor ama bazen %| ile yardım etmemiz gerekiyor. %( yerine %-( kullanınca da string değerlerin etrafına çift tırnak yazmıyor, vs. Yani, bir kere anladıktan sonra ayrıntıları da çok kolay.

Alıntı:
>
> tembel calisan algoritmalarin nasil fayda saglayacagini
>

filter'dan önce de olsa sonra da olsa sonuçta örneğin split(), elemanlardan oluşan yeni bir dizi üretir (bir veya daha fazla kere bellek ayırarak ve gerektiğinde satırları yeni yere kopyalayarak, vs.).  Örneğin, senin filter'dan önce çağrılan split() yüzünden aslında senin algoritmanın geri kalanı asıl giriş üzerinde değil, girişteki satırlardan kopyalanmış olan bir dizi üzerinde işletiliyor. (Tabii, string durumunda string'lerin içerikleri değil, gösterge+uzunluk çiftleri kopyalanır ama olsun; sonuçta yeni bir dizi oluşturulur.)

replace() de yeni bir dizi üretir. Onun yerine ben okurken splitter(' ') kullanıp yazarken de %( %) içinde virgül kullanınca hiç fazladan kopyalamamış oldum.

Ben joiner() kullanmak zorunda kalmadım ama senin join('\n') da yeni bir dizi üretir.

Ama, dediğim gibi, bu kadar küçük veri için hiç önemi yok. :)

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