Perl dersimizin bu bölümünde Perlde bağlam duyarlılığını göreceğiz.

İngilizcede diğer birçok konuşma dilinde olduğu gibi kelimelerin birden çok anlamı vardır. Mesela "left" kelimesi birçok anlam içerir:

I left the building.

I turned left at the building.

Cümlede kullanılışına göre kelimenin doğru anlamının ne olduğunu anlarız. Buna bağlam denir.

Perl 5 de buna benzer. Kelimeler, fonksiyon çağrıları ve diğer ifadeler bağlama göre farklı anlam içerir. Bu durum öğrenmeyi zorlaştırır, ama daha fazla anlamlılık sağlar.

Perl dilinde 2 önemli bağlam vardır: SCALAR ve LIST bağlam.

LIST bağlamda dizi

Bir örnek verelim:

my @words = ('Foo', 'Bar', 'Baz');
my @names = @words;

Yukaridaki atama sonrası @names dizisi @words dizi değerlerinin kopyasını içerir;

Bir diziyi başka bir diziye atama işlemi dizinin içeriğini diğer diziye kopyalar.

SCALAR bağlamda dizi

my @words = ('Foo', 'Bar', 'Baz');
my $people =  @words;

Bu kez @words dizisini $people adlı scalar bir değişkene atadık.

Diğer diller farklı davranabilir ama Perl dilinde bu atama işlemi dizinin eleman sayısını scalar değişkene kopyalar.

Bu işlem isteğe bağlıdır ve yukarıdaki kullanımın faydalı olduğu da söylenemez ama bu işlemin çok faydalı olduğu birçok başka durum vardır.

SCALAR ve LIST bağlam

Yukarıda SCALAR and LIST bağlamdan bahsettik. Anlam olarak tek bir değer (SCALAR bağlam) veya birden fazla değeri (LIST context) içermektedir. LIST bağlamda sayı değerleri 0, 1, 2 veya başka bir rakam olabilir.

if ifadesi bağlamı

Aşağıdaki örneğe bakalım:

my @words = ('Foo', 'Bar', 'Baz');

if (@words) {
   say "There are some words in the array";
}

if ifadesinin koşul kısmında bir değer bekliyoruz. Bu durumda beklenen SCALAR bağlam olmalı.

Şu an bir dizinin SCALAR bağlamdaki değerinin eleman sayısı olduğunu biliyoruz. Ayrıca eğer ki dizi boş ise bu değerin 0 (that is FALSE) olduğunu, 1 veya daha fazla eleman içeriyor ise pozitif bir sayı (that is TRUE) olduğunu da biliyoruz.

Yukarıda bahsedilen durumlardan dolayı, if (@words) kod ifadesi dizide herhangi bir eleman olup olmadığını kontrol eder ve dizi boş ise koşul sağlanmamış olur.

if-koşulunu if (! @words) şekline çevirmemiz durumunda dizi boş ise true dönecektir.

SCALAR and LIST bağlam

Bir önceki bölümde localtime() ifadesinin SCALAR ve LIST bağlamda nasıl davrandığını, şimdi ise bir dizinin SCALAR and LIST bağlamda nasıl davrandığını gördük.

Bağlam hakkında genel bir kural yoktur, özel durumları öğrenmek zorundasınız ama genellikle bunlar çok açıktır. Herhangi bir durumda perldoc kullanan bir fonksiyona bakıyor iseniz, bu fonksiyonların her biri için bir açıklama göreceksiniz. En azından SCALAR ve LIST bağlamların farklı sonuçlar verdiği durumlarda.

Şimdi daha fazla Perl ifadelerine ve ne tip bağlam oluşturduklarına bakalım.

SCALAR bağlam oluşturmak

Herhangi scalar bir değişkene ne atamasi yapar iseniz yapın bunun SCALAR bir bağlam içereceğini gördük. Bunu aşağıda açıklayalım:

$x = SCALAR;

Dizinin her bir elemanı scalar olduğundan, bunlara yapılan atamalar SCALAR bağlam oluşturur:

$word[3] = SCALAR;

Birleştirme operatörü her iki tarafında string beklediği için aşağıdaki 2 durumda da SCALAR bağlam oluşturur:

"string" . SCALAR;

ve ayrıca

SCALAR . "string"

Bu nedenle aşağıdaki kod parçası

my @words = ('Foo', 'Bar', 'Baz');
say "Number of elements: " . @words;
say "It is now " . localtime();

ekrana aşağıdakini yazacaktır

Number of elements: 3
It is now Thu Feb 30 14:15:53 1998

Sayısal operatörler genellikle 2 sayı bekler - her iki tarafta - 2 scalar. Bu yüzden sayısal operatörler her iki taraftan SCALAR bağlam oluştururlar.

5 + SCALAR;

SCALAR + 5;

LIST bağlam oluşturma

LIST bağlam oluşturmak için bazı yaplar vardır:

Diziye atama yapmak bunlardan biridir:

@x = LIST;

Bir listeye atama yapmak diğer bir yoldur:

($x, $y) = LIST;

Bu liste tek bir eleman içerse dahi durum aynıdır:

($x) =  LIST;

Bu insanları aldatmak için bize önemli bir ozellik sağlar:

Parantezler ne zaman önemlidir?

use strict;
use warnings;
use 5.010;

my @words = ('Foo', 'Bar', 'Baz');

my ($x) = @words;
my $y   = @words;

say $x;
say $y;

Ekran çıktısı:

Foo
3

Bu, parantezlerin önemli olduğu nadir durumlardan biridir.

İlk atama olan my ($x) = @words; ifadesinde bir listeye scalar değişken(ler)i atadık. Bu işlem bize sağ tarafta LIST bağlam oluşturdu. Yani dizinin değerleri sol taraftaki listeye kopyalandı. Sadece bir scalar olduğundan, dizinin ilk elemanı kopyalandı, diğerleri kopyalanmadı.

İkinci atama olan my $y = @words; ifadesinde direkt scalar bir değişkene atama yaptık. Bu işlem bize sağ tarafta SCALAR bağlam oluşturdu. SCALAR bağlamda bir dizi eleman sayısını döndürür.

Bahsedilen bu durum fonksiyona parametre geçmek konusuna geçtiğinizde çok önemli olacak.

SCALAR bağlama zorlamak

Hem print() hem de say() parametreleri için LIST bağlam oluştururlar. Peki bu durumda bir dizideki eleman sayısını ekrana basmak icin ne yazılması gerekiyor? Ya da localtime() fonksiyonundan dönen formatlı tarihi ekrana basmak isterseniz?

Asağidakini deneyelim:

use strict;
use warnings;
use 5.010;

my @words = ('Foo', 'Bar', 'Baz');

say @words;
say localtime();

Çıktı şu şekilde oluşur

FooBarBaz
3542071011113100
İlkinin anlaşılması bir şekilde mümkün, bunlar dizideki değerlerin gelişi güzel yazılmış halidir.

İkinci ise daha karmaşıktır. Bu sonuc time() fonksiyonundan dönen değer ile aynı değildir. Bu aslında localtime() fonksiyonundan LIST bağlamda dönen 9 rakamdır. Hatırlamıyorsanız the year of 19100 adlı bölümü inceleyebilirsiniz.

Çözümü SCALAR bağlamda veri döndüren scalar() fonksiyonunu kullanmaktır. Aslında bu scalar() fonksiyonunun yaptığı tüm iş denebilir. Her ne kadar bu kelimenin perl dünyasında sıkça kullanılmadığını düşünsem de, bazı insanlar bu fonksiyonu çoğul ifadeyi tekile dönüştüren casting gibi düşünebilir.


say scalar @words;
say scalar localtime();

Çıktı aşağıdaki gibi olacaktır:

3
Mon Nov  7 21:02:41 2011

Perlde bir dizinin uzunluğu veya boyutu

Perlde bir dizinin boyutunu almak isterseniz SCALAR bağlama zorlayan ve boyutunu döndüren scalar() fonksiyonunu kullanabilirsiniz.

Hileli metod

Bazen aşağıdaki gibi kod görebilirsiniz:

0 + @words;

Bu dizinin boyutunu almanın hileli bir yöntemidir. + operatörü her iki tarafta da scalar bağlam oluşturur. Bir dizi boyutunu SCALAR bağlamda döndürecektir. 0 eklemek rakamı değiştirmez, bu nedenle yukarıdaki ifade dizinin boyutunu döndürür.

scalar fonksiyonunu kullanarak biraz daha uzun ama daha net yazmanızı öneririm.