Perl dilinde kullanilan referanslar diger dillerden tanidigimiz göstergeclere (pointer) esdegerdir. Bir referans nedir? Bir degisken ile belli bir hafiza alanini adresledigimizi daha önce ögrenmistik. Referanslari kullanarak, herhangi bir degiskenin adres alanini üzerinde operasyon yapabiliriz Böylece, referansin tipine göre, referans üzerinde yapacagimiz degisklikler, degiskenin sahip oldugu degeri etkileyecektir.
Referanslari kullanarak, yüksek derecede karmasik ve dinamik programlar yazabiliriz. Dikkat edilmedigi zaman referanslar programimizin dogru calismasini engeller. Referanslar üzerinde yapilan operasyonlarla, istemeden, kullanimda olan degiskenlerin degerlerini silebilir ve degistirebiliriz. Bu göz önünüde bulundurularak, az sayida referansin kullanilmasi, programin görevini saglikli bir sekilde yerine getirmesini sagliyacaktir.
Perl dilinde iki tip referans vardir.
1. Sembolik referanslar,
2. Gercek referanslar.
Sembolik referanslar bir baska degiskenin ismini kullanarak, bu degiskenin degeri üzerinde operasyon yapabilirler. Sembolik referanslar genel anlamda kendileri ve referense ettikleri degerler degisken olduklari icin, referense edilen degerler ulasmak icin $$ isaretlerini kullanmamiz gerekiyor. Referense etmek istedigimiz veri tipine göre $$, @$, %$ kullaniyoruz.
# Degisken üzerinde sembolik referans kullanimi
$var= "Yildiz";
$semvar="var";
print $$semvar;
# Liste üzerinde sembolik referans kullanimi @araba=("Murat 131", "Sahin","Serce");
$semaraba="araba";
print @$semaraba;
# Liste üzerinde sembolik referans kullanimi
%liste=("bir", 1, "iki",2, "üc",3);
$semliste="liste";
foreach $elem (%$semliste)
{
print $elem;
}
# Subrutin üzerinde sembolik referans kullanimi
sub print
{
print "Merhaba"
}
$semsub='print';
&$semsub;
Gercek referanslar C/C++ dillerinde kullanilan göstergeclere(pointer) esgederdir. Sembolik referanslarin aksine, gercek referanslar beraberlerinde bir referans sayaci tasirlar. Bu sayac birin altina düsmedigi sürece, referense edilen hafiza alanindaki bilgi silinmez. Bunun ne anlama geldigini bir kac örnekle aciklamak istiyorum.
Örnegin bir subrutin icinde bir degisken tanimladigimizi düsünelim. Bu degisken subrutin icinde bulundugumuz sürece gecerliligini koruyacaktir. Subrutini terk ettigimiz anda, tüm local olarak tanimladigimiz degiskenler hafizadan silinir. Böylece bu degiskenlerin degerlerini ana program icinde kullanmamiz mümkün olmaz.
sub print { my $a=5; print $a; }
# Subrutin disina ciktiktan sonra $a degiskeni silinir.
Yukarda yer alan örnekte, subrutin icine girildigi andan itibaren, hafizada $a isminde bir degisken yaratilir. Son satirda yer alan print komutuyla subrutinden cikmis oluruz ve $a degiskeni hafizdan silinir.
Eger $a degiskeninin degerini ana program icinde kullanmak istiyorsak, gercek bir referans kullanarak, $a degiskenini referense edebilir ve $a degiskeninin degerini silinmekten kurtarabiliriz. Ancak ana programda $a degiskenini kullanarak, $a nin sahip oldugu degere ulasamayiz. Subrutin cikisi $a silindigi icin, anaprogram icinde böyle bir degisken mevcut olmayacaktir. Ama subrutinden cikmadan önce $a yi referense ettigimiz icin, referans ismini kullanarak, $a nin degerine ulasabiliriz.
sub print
{
my $a=5; $referans=\$a ;
}
&print;
print $$referans;
print $a;
# Son satir hatalidir, cünkü böyle bir degisken yok.
# Subrutin disina ciktiktan sonra $a degiskeni silinir.
# Ana programda $referans degiskenini kullanarak,
# $a nin degere ulasabiliriz.
\$degisken yazarak herhangi bir degiskeni referense edebiliriz.
Referans bir degiskenin sahip oldugu hafiza alani adresini icerir. Referense edilen degisken silinmis olsa bile, hafiza alani adresine sahip oldugumuz icin referans üzerinden bu bilgiye ulasabiliriz.
$var=1224;
$ptr=\$var;
print $ptr; # SCALAR(0x987c33)
# Referans bir adres icerdigi icin, print komutu bu adresi ekrana basar.
print $$ptr; # 1224
Daha önce ögrendigimiz gibi liste icinde baska bir liste yapmamiz mümkün degil. (1,2,3,(3,5)3,4) seklinde bir liste (1,2,3,3,5,3,4) olarak degerlendirilir. Bu sekilde 2 ya da 3 boyutlu bir matrix yapmamiz mümkün olmayacaktir.
Gercek referans kullanarak, bir liste elemanini diger bir listeyi gösterecek sekilde listeye yerlestirebiliriz.
Asagidaki örnegi inceleyelim.
@liste2=(3,5);
$ref=\@liste2;
@liste=(1,2,3,$ref,3,5);
foreach $elem( @liste)
{
print "$elem\n";
}
print "Alt liste\n";
print "$liste[3][0]\n";
print "$liste[3][1]\n";
#$liste[3][0], @liste2 nin birinci elemanini ekrana basar.
liste[3] listenin 4. elemani olan @liste2 yi adresler.
Referanslari kullanarak, HASH veritipi elemanlardan olusan bir liste olusturabiliriz.
$hashliste=[
{ "Bir" => 1, "Iki" => 2, "Üc" =>3 },
{ "One" =>1, "Two" =>2, "Three"=>3 } ]; $ref=\@hashliste;
print $$ref[0]{"Bir"}; # 1
print $$ref[1]{"One"}; # 1
Yazilan uzun programlarda bütün kodun bir dosya icinde yer almasi, kisa sürede kod icinde kaybolmamiza yol acabilir. Programi okunabilir ve düzenli olmasini saglamak icin kod bölümlerini ve subrutinleri baska dosyalar icine koyabiliriz. Require direktifi ile baska dosya icinde bulunan bir kodu kendi programimiza eklememiz mümkün.
################################
# var.pl icinde yer alacak kod
$var=1224;
print $var;
1;
# ana programda require
# direktifinin dogru calisabilmesi
# icin en son satirda 1 olmasi
# gerekiyor.
################################
#Ana programa var.pl dosyasini ekliyoruz
$var=111;
require "var.pl";
print $var; # 1224
Require direktifini kullanarak, programimiza disaridan kod eklememiz mümkündür. Ama Perl eklemek istedigimiz kodu nerede bulacagini nasil biliyor?
Perl derleyicis, @INC listesi icinde bulunan tüm dizinleri, eklemek istediginiz kodu bulmak icin tarar. @INC listesinin icinde yer alan dizinler:
C:\Perl\lib\MSWin32-x86
C:\Perl\lib
C:\Perl\site\5.00502\lib
C:\Perl\site\lib\MSWin32-x86
C:\Perl\site\lib
@INC listesinde yer alan dizinler sistemden sisteme degisir. Asagida yer alan programi calistirarak, sisteminiz üzerindeki Perl dizin semasini ekrana basabilirsiniz.
foreach $elem (@INC)
{
print "$elem\n";
}
Require örneginde gördügümüz gibi, disardan eklenen kodun icinde bulunan tüm degiskenler ana programda yer aldilar. Disardan eklenen kod ana programin bir parcasi olarak görülür. Bu sebepten dolayi ana programda kullandigimiz degiskenler, disardan eklenen kodun da icinde bulunabilecegi icin, zarara ugrayabilirler. Degiskenlerin gecerliliklerini koruduklari bölgeye, kod icinde isim-alani adi verilir. Bu isim-alani icinde degiskenler bellidir. Disaridan ekledigimiz kodun icinde bulunan degiskenler de, kodun icinde diger degiskenlerle ayni isim-alanini paylastiklari icin, ortaya istenmedik durumlar cikabilir. Burada, yabanci kodun, ana program icinde yer alan degiskenlerin isim-alanini kirletmeyecek sekilde, kendi isim alani icinde programa eklenmesi geregi doguyor. Aksi taktirde yabanci kodu satir satir gözden gecirerek, kullanilan degiskenleri kontrol etmemiz gerekiyor. Gözden kacirdigimiz bir degisken, programin gerektigi gibi calismasini engelleyecektir.
Isim-alanlarini birbirinden ayiracak bir mekanizmaya ihtiyacimiz var. Önümüzdeki bölümün konusu ve ayri isim-alanlari olusturmada kullanabilecegimiz paketler olacak.
Paketler yardimiyla isim-alanlarini birbirinden ayirabiliriz. Bir paket nedir ? Dilerseniz önce bu soruyu cevaplayalim.
Bir Paket basli basina bir isim-alani olusturur. Bir paket icinde yer alan tüm degisken ve subrutinler sadece paket icinde, paket ismi olmadan kullanilabilir. Paket disina cikildi zaman, paket ismini kullanarak, paket ismiyle tanimladigimiz isim-alani icindeki degisken ve subrutinlere ulasabiliriz. Böylece paket isimlerini kullanarak, isim-alanlarini birbirinden ayirmis oluyoruz.
Modüller ve Paketler:
Bir paketi, package isim; direktifini kullanarak tanimlayabiliriz. Bu direktiften sonra normal kod yazilir.
package ornek;
$var=1223;
$isim="özcan";
1;
Simdiye kadar herhangi bir paket kullanmadan, Perl programlari yazdik. Ama görmesek de, programlarimizda hep bir paket yer aldi: main. Bütün programlar main paketi ile baslar. Package komutu kullanilarak, paketler arasinda degistirme yapilir.
Simdi require direktifini kullanarak, eklenen kodda bulunan degiskenlerin ana program isim-alanini kirletmeyecek sekilde, ayri isim-alanlari yaratabiliriz.
##########################
# require ile eklenecek kod.
# var.pl
package var;
$sayi=1224;
$main::sayi= 3000;
1;
##########################
# Ana program $
sayi=1500;
require "var.pl";
print "$sayi, \n$var::sayi\n";
##########################
Program hakkinda aciklama yapmadan önce, paket kullanirken dikkat edilmesi gereken hususlara deyinmek istiyorum.
Require direktifi ile programa eklemek istedigimiz paket, isim.pl seklinde dosyalanmalidir. Perl derleyicisi, @INC listesinde bulunan dizinleri tarayarak, paketi iceren .pl dosyasini bulmaya calisir. Genelde paketi iceren dosya, eklendigi ana programin dosyasiyla ayni dizindedir.
Ana programda, requiere "paketismi.pl"; dosyasinin ana programa eklenmesini saglayacaktir.
Yukarda yer alan program nasil calisiyor? Önce ilk bölümdeki kodu var.pl ismi altinda dosyalamaniz gerekiyor. Daha sonra alt kisimda yer alan programi calisitiralim.
Program ekran cikis:
3000
1224
Ana programda $sayi degiskenini tanimladiktan sonra, require direktifi ile var paketini ana programa ekliyoruz. Paket icinde $sayi degiskenini tanimladiktan sonra main::sayi direktifiyle ana programda bulunan $sayi degiskenine 3000 rekamini esliyoruz. Paket icinde yer alan $sayi ve ana programda yer alan $sayi degiskenleri böylece birbirlerinden ayrilmis oluyor. Daha sonra ana programda, ana programin icinde tanimlanmis $sayi ve var paketinde yer alan $var::$sayi rakamlarini ekrana basiyoruz. Paket kullanilarak tanimlanmis isim-alanlarina $paketismi::$degisken seklinde ulasabiliriz.
Yukardaki örnekte görüldügü gibi, paket icinde $main::$sayi=3000; eslemesini yaparak, paket icinden, ana programda bulunan bir degiskeni degistirebiliriz.
Paket kontrüktörü BEGIN direktifi kullanilarak tanimlanir. BEGIN blogu icinde yer alan tüm komutlar pakete görevine baslamadan calistirilir. Paket kontrüktörünü kullarak, paket icinde yer alan degiskenleri belirli bir baslangic degerine esitleyebiliriz.
#################################
package pkg;
BEGIN
{
$var="$var bos degil";
}
&print_var();
sub print_var
{
print $var;
}
#################################
Paket destruktörü END direktifi kullanilarak tanimlanir. END blogu icinde yer alan komutlar program bitiminde calistirilir.
#################################
package pkg;
END
{
$var="$Program sonu geldi.";
}
&print_var();
sub print_var
{
print $var;
}
#################################
Perl modülü bir .pm dosyasi icinde yer alan bir pakettir. Daha önce kullandigimiz paket örnegini modül olacak sekilde degistirelim:
##########################
# use ile eklenecek kod.
# var.pm
package var;
$sayi=1224;
$main::sayi= 3000;
1;
##########################
##########################
# Ana program
$sayi=1500;'
use var;
print "$sayi, \n$var::sayi\n";
##########################
Ana programda use var; yazarak, modülü programimiz icinde kullanabiliriz. Use direktifi, modül icinde bulunan degisken ve subrutinleri ana programin isim-alanina yükler. Perl icin yazilmis modülleri c:\Perl\lib dizininde bulabilirsiniz. Bu modüller .pm ekini tasir ve use direktifi ile ana programa dahil edilirler.
Nesneye Yönelik Programlama:
Nesneye yönelik programlama (OOP, object oriented programming) , C++, Eiffel ve Java diliyle ortaya cikan, yeni bir programlama tarzidir.
OOP, gercek hayatta var olan nesneler örnek alinarak yazilir. Yasadigimiz dünyada hersey bir nesnedir. Her nesnenin bir calisma tarzi ve kendine has disa yönelik davranislari vadir. Bir nesne ile interaksiyona girmek icin, nesnenin icinde ne bulundugunu bilmemize gerek yok. Belirli baglamlar (Interface) üzerinden mesajlar göndererek, nesne ile baglanti kurabiliriz. Nesne bu mesaji alir ve gerekli islemleri yapar.
Perl dilini kullanarak OOP programlar yazmamiz mümkündür. OOP tarzi programlamaya gecmeden, kullanilan bazi terimlere göz atalim.
