Thread overview
string'in elemanları harf veya Unicode karakteri değil
August 30, 2010

Bu karakter kodlama ile ilgili olarak trileri projesi bize çok şey kattı. Hatta ilk orada char türünün türkçe için yeterli olamayacağını dchar kullanarak yazmamız gerektiğini söylemiştik.

Benim anladığım eğer Türkçe karakter kullanacak isek asla char türü ile ilişkimiz olmamalı. Eğer tek harf ile ilişkimiz olursa yanlış işler yapabiliriz. Örneğin SDC dosyayı string olarak okuyor ancak okurken kaçıncı satırın yanında kaçın sütunda olduğununda bilgisini tutuyor. Eğer string(char[]) türünü kullanırsa örneğin Türkçe harfler yüzünden bir sütun değil iki sütun ileri gidecek. O yüzden kaçıncı sütunda olduğunu öğrenirken dchar dchar ilerliyor.

Bu karakter işlemleri /n gibi ifadeleri okur iken beni dahada çok karıştırıyor.

Phobos'un kütüphanesi içinde bu geçerli ancak ne düşünüyorlar bilmiyorum. Ben phobos kütüphanesinde şablon kullanılmasa bile en azından in dchar kullanılması taraftarıyım.

Bu arada function yerel işlevde değilde o yerel işlevi kapsayacak değişken ile işlem yapabiliyor mu ? Ben yapabiliyor diye tahmin ediyordum ancak o zaman sizin verdiğiniz örnek kodu delegate yerine function ilede çalıştırabilmemiz gerekiyor. Ancak ben çalıştıramadım.

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

August 30, 2010

Alıntı:

>

Bu arada function yerel işlevde değilde o yerel işlevi kapsayacak değişken ile işlem yapabiliyor mu ? Ben yapabiliyor diye tahmin ediyordum ancak o zaman sizin verdiğiniz örnek kodu delegate yerine function ilede çalıştırabilmemiz gerekiyor. Ancak ben çalıştıramadım.

Tamam şu halde doğru çalışıyor:


import std.stdio;

void dene(string başlık, void function() işlem)
{

   writeln(başlık, ':');
   write("  ");
   işlem();
   writeln();

}
   string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

void main()
{
   dene("indeks ile", function(){

           for (int i = 0; i != dizgi.length; ++i) {
               write(dizgi[i], ' ');
           }
       });

   dene("foreach, tür belirtmeden", function(){
           foreach (harf; dizgi) {
               write(harf, ' ');
           }
       });

   dene("foreach, char ile", function(){
           foreach (char harf; dizgi) {
               write(harf, ' ');
           }
       });

   dene("foreach, dchar ile",  function(){
           foreach (dchar harf; dizgi) {
               write(harf, ' ');
           }
       });
}

Ancak şu halde de doğru çalışmasını bekliyordum :

import std.stdio;

void dene(string başlık, void function() işlem)
{

   writeln(başlık, ':');
   write("  ");
   işlem();
   writeln();
   string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

}

void main()
{
   dene("indeks ile", function(){

           for (int i = 0; i != dizgi.length; ++i) {
               write(dizgi[i], ' ');
           }
       });

   dene("foreach, tür belirtmeden", function(){
           foreach (harf; dizgi) {
               write(harf, ' ');
           }
       });

   dene("foreach, char ile", function(){
           foreach (char harf; dizgi) {
               write(harf, ' ');
           }
       });

   dene("foreach, dchar ile",  function(){
           foreach (dchar harf; dizgi) {
               write(harf, ' ');
           }
       });
}

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

August 30, 2010

D'nin karakter türlerinin Unicode kodlamaları olduğunu biliyoruz. Şu iki sayfada tam olmasa da biraz bilgi var:

http://ddili.org/ders/d/karakterler.html
http://ddili.org/ders/d/dizgiler.html

(Hatta onları yazdığım zaman tam anlamamış olabileceğim için yanlış bilgi bile olabilir! :D)

Digital Mars forumunda aynı konu yine açıldı. Sorun, string'in elemanlarına teker teker erişirken görülüyor:

import std.stdio;

void harfler_indeks_ile(const char[] dizgi)
{
   for (int i = 0; i != dizgi.length; ++i) {
       write(dizgi[i], ' ');
   }
   writeln();
}

void main()
{
   string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

   harfler_indeks_ile(dizgi);
}

string'in elemanları harf değil, bir kod birimi (code unit); yani harfi UTF-8 kodlamasında oluşturan birimlerin her birisi. Yukarıdaki programın çıktısı, beklendiği gibi, benim Linux konsol ortamında şöyle bozuk oluyor:

a b c � � d e f g � � h � � i j k l m n o � � p q r s � � t u � � v w x y z

Çünkü, string'i oluşturan birimler, yani 'char'lar tek başlarına anlamlı değiller.

Daha ileriye gitmeden önce, kafa karıştıran bir garipliğe dikkat çekmem gerekiyor: Yukarıdaki programda dizgi elemanından sonra yazdırılan boşluk karakterini kaldırın. Yani şu satırı kullanın:

       write(dizgi[i]);

Bu sefer çıktı düzeliyor!

abcçdefgğhıijklmnoöpqrsştuüvwxyz

Bu sonuca bakarsak, string'in elemanlarının teker teker kullanılmasında sakınca olmadığını düşünebiliriz. Çünkü sanki teker teker harfleri yazdırmış gibi oluyor. 'Ama yanlış!' Biz aslında yine de teker teker kod birimlerine erişiyoruz.

Düzgün çıkmasının nedeni, benim Linux ortamımın (belki de bütün Linux ortamlarının?) zaten UTF-8 kodlamasıyla çalışmasından kaynaklanıyor. Sonuçta, benim konsola gönderdiğim kod birimleri arka arkaya yine de anlamlı Unicode karakterleri oluşturuyorlar ve o yüzden de çıktı doğru görünüyor.

Aynı programa üç işlev daha ekleyeceğim:

import std.stdio;

void harfler_indeks_ile(const char[] dizgi)
{
   for (int i = 0; i != dizgi.length; ++i) {
       write(dizgi[i], ' ');
   }
   writeln();
}

void harfler_foreach_tür_belirtmeden(const char[] dizgi)
{
   foreach (harf; dizgi) {
       write(harf, ' ');
   }
   writeln();
}

void harfler_foreach_char_ile(const char[] dizgi)
{
   foreach (char harf; dizgi) {
       write(harf, ' ');
   }
   writeln();
}

void harfler_foreach_dchar_ile(const char[] dizgi)
{
   foreach (dchar harf; dizgi) {
       write(harf, ' ');
   }
   writeln();
}

void main()
{
   string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

   harfler_indeks_ile(dizgi);
   harfler_foreach_tür_belirtmeden(dizgi);
   harfler_foreach_char_ile(dizgi);
   harfler_foreach_dchar_ile(dizgi);
}

Çıktısı şöyle:

a b c � � d e f g � � h � � i j k l m n o � � p q r s � � t u � � v w x y z
a b c � � d e f g � � h � � i j k l m n o � � p q r s � � t u � � v w x y z
a b c � � d e f g � � h � � i j k l m n o � � p q r s � � t u � � v w x y z
a b c ç d e f g ğ h ı i j k l m n o ö p q r s ş t u ü v w x y z

Görüldüğü gibi, yalnızca sonuncusu, yani foreach döngüsünde açıkça dchar isteyeni doğru çalışıyor.

Yani, char'ın Unicode karakteri olamadığını, ama Unicode karakterlerinin UTF-8 kodlamasında kullanılan "kod birimleri" olduklarını hatırlayalım. :)

Ali

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

August 30, 2010

Aynı programı bir de delegate kullanarak yazdım:

import std.stdio;

void dene(string başlık, void delegate() işlem)
{
   writeln(başlık, ':');
   write("  ");
   işlem();
   writeln();
}

void main()
{
   string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

   dene("indeks ile", {
           for (int i = 0; i != dizgi.length; ++i) {
               write(dizgi[i], ' ');
           }
       });

   dene("foreach, tür belirtmeden", {
           foreach (harf; dizgi) {
               write(harf, ' ');
           }
       });

   dene("foreach, char ile", {
           foreach (char harf; dizgi) {
               write(harf, ' ');
           }
       });

   dene("foreach, dchar ile", {
           foreach (dchar harf; dizgi) {
               write(harf, ' ');
           }
       });
}

Gerek yoktu tabii. :) Mengü'nün lambda hatırlatmasının arkasından denemek istedim. :)

Ali

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

August 30, 2010

Alıntı (canalpay):

>

Bu arada function yerel işlevde değilde o yerel işlevi kapsayacak değişken ile işlem yapabiliyor mu ?

function, yalnızca işlevin gövdesi gibi düşünülebilir. Oluşturulduğu ortama bağlılığı bulunmuyor.

Alıntı:

>

Tamam şu halde doğru çalışıyor:

>
> import std.stdio;
>
> void dene(string başlık, void function() işlem)
> {
>
>     writeln(başlık, ':');
>     write("  ");
>     işlem();
>     writeln();
>
> }
>     string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";
>
> void main()
> {
> // ... Ali kırptı ...
>
>     dene("foreach, dchar ile",  function(){
>             foreach (dchar harf; dizgi) {
>                 write(harf, ' ');
>             }
>         });
> }
>
> ```


Tabii onun çalışmasının nedeni, 'dizgi''nin artık evrensel olması ve 'function' oluşturulduğunda onun anlaşılması. Yani derleyici için bütün bilgi mevcut.

Alıntı:
>
>
> Ancak şu halde de doğru çalışmasını bekliyordum :
>
>
>

import std.stdio;

void dene(string başlık, void function() işlem)
{

writeln(başlık, ':');
write("  ");
işlem();
writeln();
string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

}

void main()
{
// ... Ali kırptı ...

dene("foreach, dchar ile",  function(){
        foreach (dchar harf; dizgi) {
            write(harf, ' ');
        }
    });

}

>

Orada son 'foreach' satırı derlenemiyor çünkü derleyici 'foreach''teki 'dizgi''nin ne olduğunu bilemez.

Bunun nedeni, derleyici kodu bütünüyle irdelemez veya irdeleyemez. Orada ne olduğu bilinmeyen bir "dizgi" var. Ne o kapsamda bildirilmiş, ne de evrensel alanda. Derleyici o yüzden hata veriyor. Daha ileriye giderek onun gönderildiği işlevin içini de okuyarak oradaki "dizgi"nin kastedildiğine karar vermez.

Şöyle düşünelim:

if (bir_koşul) {
   dene("foreach, dchar ile",  function(){
           foreach (dchar harf; dizgi) {
               write(harf, ' ');
           }
       });
} else {
   dene_2("foreach, dchar ile",  function(){
           foreach (dchar harf; dizgi) {
               write(harf, ' ');
           }
       });}}}
}

Ya dene_2 işlevi içinde "dizgi" diye bir şey tanımlı değilse? Derleyici hata vermeli mi? Ya bir_koşul her zaman için true olacaksa? O zaman aslında hata olmamalı. vs. vs. Bu irdelemenin sonu yoktur.

O yüzden derleyici fazla derinine düşünmez ve zaten bazı durumlarda düşünemez.

Ortalığı karıştırmak için bir tane de benden: :)

import std.stdio;

void dene(string başlık, const char[] dizgi, void function(const char[]) işlem)
{
   writeln(başlık, ':');
   write("  ");
   işlem(dizgi);
   writeln();
}
void main()
{
   string dizgi = "abcçdefgğhıijklmnoöpqrsştuüvwxyz";

   dene("foreach, dchar ile",  dizgi, function(const char[] parametre_dizgi){
           foreach (dchar harf; parametre_dizgi) {
               write(harf, ' ');
           }
       });
}

O kodda main içindeki dizgi dene'ye gönderiliyor. dene de onu işlem'e parametre olarak veriyor.

dizgi'yi dene içinde yazmak ve işlem'e parametre olarak vermek de olabilir:

import std.stdio;

void dene(string başlık, void function(const char[]) işlem)
{
   writeln(başlık, ':');
   write("  ");
   işlem("abcçdefgğhıijklmnoöpqrsştuüvwxyz");
   writeln();
}
void main()
{
   dene("foreach, dchar ile", function(const char[] dizgi){
           foreach (dchar harf; dizgi) {
               write(harf, ' ');
           }
       });
}

Ali

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