February 18, 2012

Alıntı (zafer):

>

Alıntı (Salih Dinçer):

>

void diziyeEkleÇıkart (ref int[] d, int e, bool ekleyim_mi)

...

dizinin 'ref' anahtar kelimesi ile işaretlenmiş olması, bildiğimiz gibi diziler metotlara zaten referans olarak aktarılırlar yani ekstradan bizim bunu referans olarak işaretlememiz gerekmez.

Hem çok doğru, hem bazen yanlış. ;)

(Tabii dizi derken özellikle dilimleri, yani dinamik dizileri kasdettiğinin farkındayız. Çünkü sabit uzunluklu diziler değer türleridir; onlar kopyalanırlar.)

Ama "referans olarak işaretlememiz gerekmez" derken dilimler için bile yanlış oluyor.

Evet, ref kullanmazsak main içindeki dilimle işlev içindeki dilim aynı elemanlara erişim sağlamaktalar. Referans türü olmalarının etkisi bu. Ama iki dilim aynı dilim değiller. İşlev içindeki dilime yapılan bazı değişiklikler main içindeki dilim tarafından görülmez. Bunun bir etkisi şurada "Uzunluğun artması paylaşımı sonlandırabilir" başlığında vardı:

http://ddili.org/ders/d/dilimler.html

Daha da ayrıntılı bilgi şurada "Belirsizlik" başlığında vardı:

http://ddili.org/makale/d_dilimleri.html

İşte o belirsizlik konusu çok dikkat etmemiz gereken bir konu. Orada aynı başlık altındaki iki madde, izlenmesi gereken ilkeleri içeriyor.

Öte yandan, eğer ref kullanılırsa main içindeki ve işlevdeki dilimler aynı dilim oluyorlar. Yani o zaman zaten tek dilim oluyor ve belirsizlik kalmıyor. Ama tabii her zaman ref koyulması doğru değil. Bu ayrımı bilmemiz önemli.

Ali

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

February 19, 2012

Alıntı (Ali Çehreli:1329513339):

>

Bağlı listenin de yararları var: eleman eklemek ve çıkartmak, topluluktaki başka elemanları göstermekte olan referansları bozmaz. Dizide öyle değildir: tek eleman eklemek ya sonrakileri bir adım kaydırır; ya da bütün diziyi olduğu gibi başka yere taşır. Eleman çıkartmak da öyle: çıkartılan elemandan sonrakiler bir hane sola kayarlar. Bağlı listede öyle bir sorun yok.

Ama elimizdeki bu örnekte dizi bağlı listeyi kat kat geçiyor. Göstergelere çok bağlı bir kavramdır. Onun için şu bölümde "Basit bir bağlı liste" başlığı ile geçmiş:

http://ddili.org/ders/d/gostergeler.html

O bölümün üçüncü problemini de sana bırakıyorum! ;)
Bağlı listeleri çok merak ediyorum ve onlar hakkında sitede ne var ise hatim etmek isterim. Gerçi hala bu uygulamaya nasıl uyarlayabileceğimizi anlayamadım; bir örnek gösterirseniz sevinirim.

Alıntı (Ali Çehreli):

>

Alıntı:

>

Stroustrup, sanırım aslen Alman

Danimarkalı. Sizin televizyon Wikipedia'yı çekmiyor mu? ;)

http://en.wikipedia.org/wiki/Bjarne_Stroustrup

Ali

Türkçe olan sayfalara bakmıştım ama doğru düzgün bilgiler olmadığını görünce derinlemesine araştırmadım. Bu isimleri henüz yeni tanıyorum. Meğer camianın duayenleriymiş. Aynı etkinlikte birlikte oturarak konuştukları vidyoda, kimse ilk sözü almıyor ve Stroustrup'u (saygıdan olsa gerek) gösteriyorlar. İkinci söz olarak Alexandrescu'ya bakıyor ama o da çok mütevazi görünüyor.

Alıntı (zafer):

>

Alıntı (Salih Dinçer):

>

void diziyeEkleÇıkart (ref int[] d, int e, bool ekleyim_mi)

...

dizinin 'ref' anahtar kelimesi ile işaretlenmiş olması, bildiğimiz gibi diziler metotlara zaten referans olarak aktarılırlar yani ekstradan bizim bunu referans olarak işaretlememiz gerekmez.
Gereksiz olduğunu bilmiyordun ve gerektiği için koymuştum... :rolleyes:

Aslında gereksiz şeyleri kullanmamam ve kodları feci derecede kısaltmamla ünlüyümdür...:)

Bu uygulamamızda tekrar hafızada yeni bir şey tanımlamak yerine ref kullanarak üzerinde işlem yapılan diziyi göstermeyi yeğledim. Başka bir yöntem var mı? Tamam, diziyi 'main()' dışında tanımlarsak her yerden (global) ulaşılabilecek ama bu da bana açıkçası çok zarif görünmedi...

Sevgiler, saygılar...

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

February 19, 2012

Alıntı (erdem:1329515374):

>

Bu kadar tesadüf olur! :-p

Ben de tam Çizgi TAGEM araştırma geliştirme ekibinin hazırlamış olduğu sayısal devreler (http://www.cizgi-tagem.org/e-kampus/education.aspx?key=digital2010) konulu dersleri okuyordum. Boole Aritmetiği gerçekten çok zevkli ve ilginç bir konu.
:)

TAGEM'i biliyorum, bir ara üye olmuştum ama dersleri devam ettiremedim. Aslında orada bilmediğim ve öğrenmemin faydalı olabileceği çok şey var. Ama bildiklerim tekrar etmek sıkıcı geliyor. Gerçi ders atlama var ama arada unuttuklarım da olabilir. Aklımda kaldığı kadarıyla elektronik konusunda (uzmanlığım sayısal, PIC) yardıma ihtiyaç duyarsan seve seve ilgilenmek isterim.

Alıntı (erdem:1329515374):

>

C++ için bu veri yapılarının karşılıkları 'std::vecto'r ve 'std::list''dir.

Vektör tek uçlu bir dinamik dizi gerçeklemesidir. Vektör rastgele erişime izin verir. Yani operator [] işlecini kullanarak belirli bir sıradaki elemana erişebilirsiniz. Vektörün en sonuna eleman eklemek ve çıkarmak çok hızlıdır. Ancak vektörün --başına ya da ortasına-- eleman eklemek yavaştır çünkü tüm elemanların sırayı bozmadan kaydırılmaları gerekir.

Liste ise bir çift bağlı liste gerçeklemesidir.Bu demektir ki her eleman kendine ait bir bellek alanı işgal eder. Listeler rastgele erişime izin vermezler. Örneğin 10. elemana erişmek için ilk 9 eleman arasından zinciri takip ederek yol almalısınız. Listenin avantajı --herhangi bir konuma eleman eklenmesi veya çıkarılması çok hızlıdır-- Sadece bağların değiştirilmesi yeterlidir.Bu da bir listenin ortasına bir eleman eklemenin bir vektör ya da listeye kıyasla çok hızlı olduğu anlamına geliyor.

Teşekkürler...

Her geçen gün dizi ve liste kavramını daha çok anlıyorum...:)

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

February 18, 2012

Alıntı (zafer):

>

Sanırım bu belirsiz durumlar için yan etki üreten değilde değer döndüren metotlarla çalışmak daha doğru bir seçim gibi görünüyor.

Kesinlikle! :) Değer döndürünce işlev tasarımları çok daha basit oluyor.

Ali

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

February 19, 2012

Bazen çok kibar olabiliyorum...:)

Dizi'yi mi, Liste'yi mi tartışalım bilemedim ama sanırım dizilerle oluşturduğumuz kodun ekleme, sıralama ve çıkarma dahil tamamını yapabiliyoruz. Ali hocamın dediği gibi belirsizliği düzeltmek için iki işlev haline getirdim. Ama ref olayını çok sevdim...:)

/*
diziyeEkle.d (17.02.2012)
*/
import std.array, std.stdio, std.random;

void diziyeEkle(ubyte e, ref ubyte[] d){
   uint k;                                 // Konum
   auto dizi = appender!(ubyte[])();

   for(k = 0; k < d.length; k++) if(e < d[k]) break;
   dizi.put(d[0 .. k]);
   dizi.put(e);
   dizi.put(d[k .. $]);
   d = dizi.data;
}

void dizidenÇıkart(ubyte k, ref ubyte[] d){
   auto dizi = appender!(ubyte[])();

   dizi.put(d[0 .. k]);
   dizi.put(d[k + 1 .. $]);
   d = dizi.data;
}

void main (){
   ubyte [] dizi;
   ubyte [] s = [ 1, 3, 5, 7, 9, 0,  2, 4, 6, 8 ];
   auto r = Random(unpredictableSeed);

   foreach(e; randomCover(s, r)) diziyeEkle(e, dizi);
   dizidenÇıkart(6, dizi);
   writeln("Diziden çıkan~~~~v\n", dizi);
}

Çıktısı:
'Diziden çıkan~~~~v
[0, 1, 2, 3, 4, 5, 7, 8, 9]'

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

February 19, 2012

Alıntı (Salih Dinçer):

>

Bu uygulamamızda tekrar hafızada yeni bir şey tanımlamak yerine ref kullanarak üzerinde işlem yapılan diziyi göstermeyi yeğledim.

Evet, benim de sonradan yazdığım gibi, o programdaki ref, dilime eleman eklenip çıkarıldığı için gerekliydi. Ama "üzerinde işlem yapılan" diye açıklanabiliyor olması 'ref' kullanımını gerektirmez. Burada ilginç olan, 'ref' kullanımının gerekip gerekmemesi işlemin çeşidine bağlı oluyor. (Bunları zaten biliyoruzdur; yalnızca altını çiziyorum. :))

Örneğin, işlem elemanların değerlerinin iki katlarını almak olduğunda 'ref' olsa da olur olmasa da. Hatta, 'ref' kullanmamak, dilimlerin referans türü karakterleri nedeniyle daha mantıklı görünebilir ve senin "gereksiz şeyleri kullanmamam ve kodları feci derecede kısaltmamla ünlüyümdür" sözüne de daha çok uyar:

void ikiyeKatla(int[] dilim)
{
   foreach (ref eleman; dilim) {
       eleman *= 2;
   }
}

void ikiyeKatla_ref(ref int[] dilim)
{
   foreach (ref eleman; dilim) {
       eleman *= 2;
   }
}

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

   ikiyeKatla(dizi);
   ikiyeKatla_ref(dizi);

   assert(dizi == [ 4 ]); // <-- ikisi de main'deki elemanları ikiye katlamış
}

foreach'lerdeki 'ref' ise o örnekte zaten her durumda gerekir. Umarım o ref'ler öreği karıştırmıyorlardır. Yoksa aynı örnek foreach'ler şu biçim yazılarak da gösterilebilirdi:

void ikiyeKatla(int[] dilim)
{
   foreach (i; 0 .. dilim.length) {
       dilim[i] *= 2;
   }
}

void ikiyeKatla_ref(ref int[] dilim)
{
   foreach (i; 0 .. dilim.length) {
       dilim[i] *= 2;
   }
}

Hatta for döngüsü de kullanılabilirdi. Sonuçta, öyle bir örnekte dilimleri 'ref' olarak alıp almamanın bir etkisi olmuyor, çünkü işlemler elemanları değiştirmek için kullanılıyorlar.

'ref', eleman eklemek veya çıkartmak gibi dilimin anlamı ile ilgili işlemlerde gerekiyor. (Bunu da Salih'in örneğinde gördük. Parametre 'ref' olmasaydı elemanlar yalnızca işlev içindeki dilim tarafından görülürdü; çünkü o dilim uzadıkça main'deki dilimden farklı elemanlara erişim sağlamaya başlardı.)

Alıntı:

>

Başka bir yöntem var mı?

Aslında evet. Başka bir yöntem, Zafer'in de önerdiği gibi sonuç diziyi döndürmek olabilir. Şimdi dilime eleman ekleyen iki işlev yazalım. Birisi 'ref' olarak alıyor ve parametre olarak gelen o dilime ekliyor (Salih'in işlevi gibi), diğeri de yeni bir dilim döndürüyor:

void elemanEkle_ref(ref int[] dilim, size_t adet)
{
   foreach (i; 0 .. adet) {
       dilim ~= 1;
   }
}

int[] elemanEkle(int[] dilim, size_t adet)
{
   int[] sonuç = dilim;

   foreach (i; 0 .. adet) {
       sonuç ~= 1;
   }

   return sonuç;
}

İkincisi bütün diziyi döndürüyor gibi göründüğü için yavaş diye düşünülebilir ama öyle değildir. Çünkü dilimler perde arkasında bir göstergeden ve bir uzunluktan oluşurlar.

Ama ikincisinin bir tehlikesi var: Bu, yukarıdaki bağlantılarda "paylaşımın sonlanması" ve "belirsizlik" gibi kavramlar olarak geçiyor. 'adet' küçük bir değer olduğunda sonuç ile parametrenin ilk elemanları aynı elemanlar oluyorlar.

Alıntı:

>

Tamam, diziyi 'main()' dışında tanımlarsak her yerden (global) ulaşılabilecek ama bu da bana açıkçası çok zarif görünmedi...

Çok kibarsın. ;) Keşke global değişkenlerin tek sorunları zarif olmamaları olsa. :)

Ali

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

February 19, 2012

Alıntı (acehreli):

>
> void elemanEkle_ref(ref int[] dilim, size_t adet)
> {
>     foreach (i; 0 .. adet) {
>         dilim ~= 1;
>     }
> }
>
> int[] elemanEkle(int[] dilim, size_t adet)
> {
>     int[] sonuç = dilim;
>
>     foreach (i; 0 .. adet) {
>         sonuç ~= 1;
>     }
>
>     return sonuç;
> }
> ```

>
> Ama ikincisinin bir tehlikesi var: Bu, yukarıdaki bağlantılarda "paylaşımın sonlanması" ve "belirsizlik" gibi kavramlar olarak geçiyor. 'adet' küçük bir değer olduğunda sonuç ile parametrenin ilk elemanları aynı elemanlar oluyorlar.
>

Buradaki tehlikeyi tam olarak anlamadım Ali, ben şöyle düşünüyorum; elemanEkle() metotunun içinde zaten sonuç isimli yeni bir dizi (dilim) tanımlıyoruz, dolayısıyla bu dizi üzerinde işlemleri yapıp geriye yine bunu döndürüyoruz. Bunun uzaması veya kısalması yani paylaşımın sonlanması veya gönderilen dilim ile başka bir adresi göstermesi artık önemli değil nedeni ise basit bu metodun dönüşünde artık elimizde yeni bir dizi oluyor ve bizim çalışmaya devam edeceğimiz dizi de bu dizi olmak zorunda değil mi? Atladığım bir konu mu var?

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

Ali hocam,

Belki seni çok basit konularda meşgul ediyoruz. Bu foruma üye olmamış olsaydım herhalde sana harcattığım zamanı belki ailen ile geçirecektin. O yüzden hakkını helal et lütfen... :blush:

Böyle duygular ile istemeyerek yine meşgul edici bir soru soracağım! Tamam, dizilerin sıralı mantığını ve dilimlerin çöp toplayıcısı ile iş birliğini anladım. Ama şu yapılar ile oluşturulan listeler (linked list) yok mu, çok şaşırtıcı. Örneğin:

Şu şekilde listemi oluşturuyorum: foreach(r; rakamlar) soy.ekle(r, yedek);

Çıktısı:

'AĞAÇdakiler~~~~~v
0 @BFB4E214
1 @BFB4E174
2 @BFB4E0D4
3 @BFB4E034'

ve bir güzel başına ekleme yapıyorum: soy.başınaEkle(5, soy); Kodu ise basit, şu:

void başınaEkle(ubyte değeri, ref AĞAÇ* boğumu)
{
   boğumu = new AĞAÇ(değeri, boğumu);
}

Bu durumda aynı çalışma anında bunun gibi ilginç bir sonuç çıkıyor:

'AĞAÇdakiler~~~~~v
5 @BFB4E214
0 @BFB4E174
1 @BFB4E0D4
2 @BFB4E034
3 @BFB4DF94'

Tamam, öngördüğümüz gibi başına ekliyor ama dikkat E214 ile biten 0 değerli eleman yerine başına eklediğim geliyor ve diğerleri aynı bellek değerleri ile aşağıya kayıyor! Allah Allah, bu nasıl bağlı liste? Eğer bütün dillerde böyle çalışıyorsa herhalde yavaş olur diye düşünmeden edemiyorum... :rolleyes:

Teşekkürler...

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

February 20, 2012

:-D

Haklısınız, helal olsun...:)

Hemen açtım: http://ddili.org/forum/thread/728

Cevabınızı dört gözle bekleyeceğim...

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

February 20, 2012

Alıntı (zafer):

>

bu metodun dönüşünde artık elimizde yeni bir dizi oluyor ve bizim çalışmaya devam edeceğimiz dizi de bu dizi olmak zorunda değil mi?

Asıl dizinin hemen arkasında boş yer olduğunda yeni dilime eklenen elemanlar için orası kullanılıyor. Asıl dizi yine az elemana erişim sağlamaya devam ediyor, yeni dizi de daha fazla elemana erişim sağlıyor. Ama işte öyle olduğunda baştaki elemanların paylaşımı devam ediyor.

import std.stdio;

int[] elemanEkle(int[] dilim, size_t adet)
{
   int[] sonuç = dilim;

   foreach (i; 0 .. adet) {
       sonuç ~= 1;
   }

   return sonuç;
}

void main()
{
   int[] asıl = [ 2, 3, 4, 5, 6, 7, 8, 9 ];
   int[] yeni = elemanEkle(asıl, 5);

   yeni[0] = 42;   /* <-- Bu işlem asıl dizideki elemanı etkiler mi etkilemez
                    *     mi? İşin kötüsü, adet olarak örneğin 5
                    *     kullanıldığında etkiliyor ama örneğin 10
                    *     kullanıldığında etkilemiyor! İşte 'belirsizlik'
                    *     orada. */
   writeln(asıl);
}

Çıktısı:

'[42, 3, 4, 5, 6, 7, 8, 9]'

Görüldüğü gibi, yeni dizinin elemanını değiştirince asıl dizinin elemanı da değişiyor. Ama 5 yerine daha büyük bir adet kullanınca paylaşım bozulmuş olabilir ve paylaşım kalmamış olabilir.

Ali

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