Yazımızın geçen ayki bölümünde Perl 6'nın gelişim sürecinden bahsedip, irili ufaklı birçok yeni özelliğini örnek kodlar eşliğinde görmüştük. Bu ay, Perl 6'nın daha büyük ve çoğu diğer popüler programlama dillerinde bulunmayanyeni özelliklerine değineceğiz.

Hiper İşleçler (Hyper Operators)

Perl 6'da her normal işlecin bir de hiper karşılığı var. Hiper işleçler liste bağlamında iş görüyor ve her iki tarafındaki listelerin elemanlarını birbiri ile eşleyerek işlemini yerine getiriyor. Hiper işleçler bir işlecin iki yanına >> ve << karakterlerinin getirilmesi ile oluşturuluyor:

use v6; my @sayilar_1 = (1, 3, 5);
my @sayilar_2 = (2, 4, 6);

# Her iki dizinin de elemanlarını birbiri ile topla.
my @toplamlar = @sayilar_1 >>+<< @sayilar_2;

# Dizinin güzel bir şekilde görüntülenmesi için .perl metodunu kullanacağız.
# Bu metod hata ayıklamada kullanılmak üzere yaratılmıştır ve her türlü nesne
# üzerinde kullanılabilir.

@toplamlar.perl.say;
# Çıktı: [3, 7, 11]

Bağlaçlar (Junctions)

Bağlaçlar, mantık işlemlerini ifadeler yerine değerler üzerinde uygulayabilmemizi sağlayan bir kavramdır. Teorik olarak anlatması zor olsa da aşağıdaki örnekleri okuyunca muhtemelen kolayca anlayacaksınız. Örneğin, elimizde 2, 4 ve 5 sayıları var. Biz de Perl'e "bu sayılardan herhangi biri", "bu sayılardan yalnızca biri", "bu sayıların hepsi" gibi kavramları anlatmak istiyoruz. Bunu artık aşağıdaki şekilde yapabiliyoruz:

use v6;

# Sayılardan herhangi biri:
my $sayilar = 2 | 4 | 5;

if $sayilar < 3 {
 say "Sayılardan herhangi biri 3'ten küçük."; 
 # Çıktı verecek çünkü 2 sayısı 3'ten küçük.
} 

# Sayılardan yalnızca biri: 
$sayilar = 2 ^ 4 ^ 5; 

if $sayilar > 4 { 
 say "Sayılardan yalnızca biri 4'ten büyük."; 
 # Çıktı verecek çünkü yalnızca 5 sayısı 4'ten büyük.
} 

# Sayıların hepsi: 
$sayilar = 2 & 4 & 5; 

if $sayilar >= 4 {
 say "Sayıların hepsi 4'ten büyük veya 4'e eşit.";
 # Çıktı vermeyecek çünkü 2 sayısı 4'ten büyük veya 4'e eşit değil.
} 

# Çıktı: Sayılardan herhangi biri 3'ten küçük. 
# Sayılardan yalnızca biri 4'ten büyük.

Akıllı Eşleme (Smart Match)

Akıllı eşleme, bazı sıkça kullandığımız karşılaştırma işlemlerini kolaylaştıran bir işleç olan ~~ karakterleri ile yapacağımız işlemlere verilen addır. Bu işleç iki tarafında bulunan verilerin türüne göre farklı davranışlar sergiliyor. En basitinden, bir skaler veri ile bir metin arasında akıllı eşleme yaparsak ~~ işleci bize her iki taraftaki verilerin birbirine eşit olup olmadığını veriyor:

use v6; 
my $isim = "Canol"; 
if $isim ~~ "Canol" { 
 say "İsminiz Canol."; 
} 
# Çıktı: İsminiz Canol.

Eğer bir skaler veri ile tanımlanmamış bir değer arasında akıllı eşleme yaparsak, geriye o skaler değerin tanımlanmış olup olmadığı bilgisi dönüyor:

use v6;
 my $isim;
 if $isim ~~ undef {
 say "İsminiz tanımlanmamış.";
}
 # Çıktı: İsminiz tanımlanmamış.

Bir kuralı (kuralların ne olduğuna ileride geleceğiz) bir metin ile eşleyebiliyoruz. Bu durumda ~~ işleci kuralın gerçekleşip gerçekleşmediğini dönüyor. Aşağıdaki kod Rakudo'daki bir hatadan dolayı şimdilik çalışmıyor:

use v6;
 my $isim = "Canol"; 
if $isim ~~ s/Canol/Necip/ { 
 say "İsminiz artık Necip."; 
} 
# Çıktı: İsminiz artık Necip.

Akıllı eşleme ile birçok karmaşık işlem yapılabiliyor. Örnek olarak, aşağıdaki kod iki sözlük arasında ortak olan bir anahtar kelime olup olmadığını kontrol ediyor. Yine Rakudo'dan dolayı aşağıdaki kod henüz çalışmıyor:

use v6;
 my %sozluk_1 = ("Anahtar1" => "Deger1", "Anahtar2" => "Deger2"); 
my %sozluk_2 = ("Anahtar3" => "Deger3", "Anahtar1" => "Deger4"); 
if %sozluk_1 ~~ %sozluk_2 { 
 say "İki sozlük arasında ortak olan bir anahtar kelime var."; 
}
 # Çıktı: İki sozlük arasında ortak olan bir anahtar kelime var.

Bloklar (Blocks) ve Kaplamlar (Closures)

Perl 5'te C temelli tüm dillerde olduğu gibi küme parantezi içerisine alınan deyimler kendi yerel kapsamlarına sahip bir blok oluşturuyordu. Perl 6'da bloklara yeni bir özellik eklendi. Bu özelliğe göre Perl 6'daki bütün bloklar aynı zamanda bir kaplam. Yani bir bloğu daha sonra çalıştırılmak üzere bir değişkene atayabiliyor veya işlevlere argüman olarak gönderebiliyoruz:

use v6; my $kaplam = { say "Merhaba!"; } $kaplam();

Çıktı: Merhaba!

Dilbilgileri (Grammars) ve Kurallar (Rules)

Perl 6'da yapılan en önemli değişikliklerden biri de Perl deyince akla gelen ilk özelliklerden biri olan düzenli ifadelerde (regular expressions) oldu. Düzenli ifadeler Perl ile ünlü olmuş, Perl'den sonra çıkan birçok programlama dili düzenli ifadelere destek vermeye başlamıştı. Ancak üzerinden seneler geçmesine rağmen düzenli ifadelere büyük yenilikler eklenmedi. Ayrıca, düzenli ifadeler en çok kullanılan özelliklerden biri olmasına rağmen oldukça kafa karıştırıcı kurallara sahipti. Üstelik bir dilin içinde sanki başka bir dil kullanılıyor hissi uyandırıyordu.

Tüm bu faktörler bir araya gelince Perl 6'nın yapımına başlayan ekip, düzenli ifadeleri artık baştan ele almanın zamanının geldiğini düşündüler. Hatta düzenli ifadelerin bugünkü halini yaratan programlama dilinin yeni sürümünü geliştirdiklerini düşününce sorumluluk hissettiler bile denebilir.

Değişiklikler, bu kavramın isminden başladı. Büyük değişikliklerin planlanması üzerine bu kavramı daha iyi anlatan bir isim olarak "kurallar"da (rules) karar kılındı. Temel değişiklikler, düzenli ifadelerin daha okunaklı olması ve özyinelemeli ayrıştırmaya (recursive descent parsing) izin vermesi olarak özetlenebilir. Dilbilgileri ise birkaç kuralın bir araya gelerek oluşturdukları yapıya deniyor. Kurallar aşağıdaki şekilde tanımlanıp kullanılabiliyor:

use v6;
 my $cumle = "Emre kapıdan içeri girdi."; 
# Kuralımızı tanımlıyoruz. rule isimler { Canol | Necip | Emre | Zeliha }; 
# Akıllı eşleme yoluyla kuralımızı $cumle üzerinde uyguluyoruz. Düzenli ifade
# kullanma söz dizimine ilaveten kuralımızı, metin sabitlerinden (string 
# literal) ayırmak amacıyla üçgen parantezler arasına alıyoruz.

 if $cumle ~~ // {
 say "Hoşgeldiniz.";
} else {
 say "Üzgünüz, davetli değilsiniz.";
} 
# Çıktı: Hoşgeldiniz.

Perl 6, Perl 5 düzenli ifadelerine birçok yeni meta karakter (metacharacter), kaçış ardılı (escape sequence) ekliyor. Bunun yanında bazı mevcut simgelerin ise anlamları değişiyor. Örneğin artık . (nokta) meta karakteri yeni satır karakterini de eşliyor. [ ve ] köşeli parantezleri artık desenleri yakalamadan (noncapturing) gruplamaya yarıyor. { ve } küme parantezleri kuralımızın içinde kaplamlar yani Perl 6 kodu çalıştırmaya yarıyor. Veya bir deseni n kere eşlemek için niceleyici (quantifier) olarak {n} değil de ** n yazıyoruz.

Perl 6'da niteleyicilerin (modifiers) yerleri de değiştirildi. Örneğin, büyük/küçük harfe duyarsız (caseinsensitive) eşlemeler yapmak için kullanılan i niteleyicisi veya birden fazla (global) eşleme yapmak için kullanılan g niteleyicisi, kuralın başına getiriliyor ve neteleyiciden önce bir : (iki nokta üst üste) karakteri konuluyor. Aşağıdaki kod bu özelliğe bir örnek teşkil ederken henüz Rakudo'da çalışmıyor. O yüzden uyguladığınız taktirde bir hata alacaksınız. Yine de Perl 6 standardına uyan bir kod olması nedeniyle yakın zamanda çalışır hale gelecektir:

use v6; 
my $cumle = "Zeliha: \"Artık canıma tak etti!\" dedi.";
 # Büyük/küçük harf duyarlı kural. rule ozel_isim_can { Can }; 
 # Büyük/Küçük harf duyarsız kural. rule can :i { Can }; 

if $cumle ~~ // {
 say "Cümlede özel isim olan \"Can\"ı kullandınız."; 
}
 if $cumle ~~ // {
 say "Cümlede \"can\" kelimesini kullandınız."; 
}
 # Çıktı: Cümlede "can" kelimesini kullandınız.

Bir dilbilgisi yazarak, BNF sunumunu bildiğimiz herhangi bir programlama dili için ayrıştırıcı hazırlayabiliriz. token anahtar kelimesinin rule anahtar kelimesinin çok benzeyen bir alternatifi olduğunu belirterek, örneğin Pascal programlama dilinin dilbilgisinin ilk adımlarından birini atıp bir tanımlayıcının (identifier) kuralını yazalım. Çoğu dilde olduğu gibi Pascal'da da bir tanımlayıcı ilk harfinde bir rakam olmamak şartıyla harf, rakam ve alt çizgi karakterlerinden oluşur. Aşağıdaki kod Pascal dilbilgisini ve bu kuralları oluşturuyor, sonra da birkaç ifadenin doğru bir tanımlayıcı olup olmadığını kontrol ediyor:

use v6;
 # Dilbilgisini tanımlıyoruz. 
grammar Pascal { 
# Kurallarımızı tanımlıyoruz.
 token rakam { 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 }; 
 token harf { <[a..zA..Z]> };
 token tanimlayici_isim { ^( | _ ) ( | | _ )* }; 
} 

my $ifade_1 = "degisken_1"; 
my $ifade_2 = "2_degisken";
 my $ifade_3 = "_islev";

# Bir dilbilgisinin içindeki kurala, ilk dilbilgisinin ismini yazıp daha 
# sonra :: karakterlerini koyup daha sonra da kuralın adını yazarak ulaşıyoruz. 
if $ifade_1 ~~ // {
 say "ifade_1 doğru bir tanımlayıcı isimdir."; 
} else { 
 say "ifade_1 doğru bir tanımlayıcı isim değildir."; 
} 

if $ifade_2 ~~ // {
 say "ifade_2 doğru bir tanımlayıcı isimdir.";
} else { 
 say "ifade_2 doğru bir tanımlayıcı isim değildir."; 
} 

if $ifade_3 ~~ // {
 say "ifade_3 doğru bir tanımlayıcı isimdir."; 
} else {
 say "ifade_3 doğru bir tanımlayıcı isim değildir.";
 } 
# Çıktı: ifade_1 doğru bir tanımlayıcı isimdir.
# ifade_2 doğru bir tanımlayıcı isim değildir.
# ifade_3 doğru bir tanımlayıcı isimdir.

Gelecek

Bu yazıda sizleri Perl 6'nın gelişim süreci hakkında bilgilendirmeye çalıştık, daha sonra da birlikte bu yeni tasarlanan dildeki değişikliklere şöyle bir göz ucuyla baktık. Eski Perl sürümleri gibi Perl 6 da devasa bir dil. Perl 5'ten sonra çıkan dillerdeki güzel özellikleri kendisine uyarlamaya çalışırken bazı yeni fikirleri de bizlere ilk defa sunmaya çalışacak. Kaybettiği ilgiyi tekrar kazanabilecek mi, eski popüler günlerine dönebilecek mi sanıyorum birkaç ay içerisinde göreceğiz. Dileğimiz Perl 6'nın, programlama dünyasını ileriye taşıyabilecek güzel bir katkı olarak tarihteki yerini alması...

Kaynaklar