Sol Değerler ve Sağ Değerler
Her ifadenin değeri ya sol değerdir ya da sağ değerdir. Bu iki kavramı ayırt etmenin kolay bir yolu, dizi ve eşleme tablosu elemanları dahil olmak üzere bütün değişkenlerin sol değer, hazır değerler dahil olmak üzere bütün geçici değerlerin de sağ değer olduklarını kabul etmektir.
Örneğin, aşağıdaki writeln()
çağrılarından birincisinin bütün parametreleri sol değerdir, ikincisindekiler ise sağ değerdir:
import std.stdio; void main() { int i; immutable(int) imm; auto dizi = [ 1 ]; auto tablo = [ 10 : "on" ]; /* Aşağıdaki parametre değerlerinin hepsi sol değerdir. */ writeln(i, // değişken imm, // immutable değişken dizi, // dizi dizi[0], // dizi elemanı tablo[10]); // eşleme tablosu elemanı // vs. enum mesaj = "merhaba"; /* Aşağıdaki parametre değerlerinin hepsi sağ değerdir. */ writeln(42, // hazır değer mesaj, // enum sabiti (manifest constant) i + 1, // geçici değer hesapla(i)); // işlevin dönüş değeri // vs. } int hesapla(int i) { return i * 2; }
Sağ değerlerin yetersizlikleri
Sol değerlerle karşılaştırıldıklarında sağ değerler aşağıdaki üç konuda yetersizdir.
Sağ değerlerin adresleri yoktur
Sol değerlerin bellekte yerleri olabilir, sağ değerlerin olamaz.
Örneğin, aşağıdaki programdaki a + b
sağ değerinin adresi alınamaz:
import std.stdio; void main() { int a; int b; readf(" %s", &a); // ← derlenir readf(" %s", &(a + b)); // ← derleme HATASI }
Error: a + b is not an lvalue
Sağ değerlere yeni değer atanamaz
Değişmez olmadıkları sürece sol değerlere yeni değer atanabilir, sağ değerlere atanamaz.
a = 1; // ← derlenir (a + b) = 2; // ← derleme HATASI
Error: a + b is not an lvalue
Sağ değerler işlevlere referans olarak geçirilemezler
Sol değerler referans olarak geçirilebilirler, sağ değerler geçirilemezler.
void onArttır(ref int değer) { değer += 10; } // ... onArttır(a); // ← derlenir onArttır(a + b); // ← derleme HATASI
Error: function deneme.onArttır (ref int değer)
is not callable using argument types (int)
Bu kısıtlamanın temel nedeni, işlevlerin referans türündeki parametrelerini sonradan kullanmak üzere bir kenara kaydedebilecekleri, oysa sağ değerlerin yaşamlarının sonradan kullanılmaya çalışıldıklarında çoktan sonlanmış olacağıdır.
C++ gibi bazı dillerden farklı olarak, D'de sağ değerler referansı const
olarak alan işlevlere de geçirilemezler:
void yazdır(ref const(int) değer) { writeln(değer); } // ... yazdır(a); // ← derlenir yazdır(a + b); // ← derleme HATASI
Error: function deneme.yazdır (ref const(int) değer)
is not callable using argument types (int)
Hem sol değer hem sağ değer alabilen auto ref
parametreler
Önceki bölümde gördüğümüz gibi, işlev şablonlarının auto ref
parametreleri hem sol değer hem sağ değer alabilirler.
auto ref
, bir sol değer ile çağrıldığında referans olarak geçirme anlamına gelir; sağ değer ile çağrıldığında ise kopyalayarak geçirme anlamına gelir. Derleyicinin bu farklı iki durum için farklı kod üretebilmesi için işlevin bir şablon olması gerekir.
Şablonları daha sonra göreceğiz. Şimdilik aşağıda işaretli olarak gösterilen boş parantezlerin onArttır
'ı bir işlev şablonu haline getirdiğini kabul edin.
void onArttır()(auto ref int değer) { /* UYARI: Asıl parametre bir sağ değer ise buradaki * 'değer' adlı parametre çağıran taraftaki değerin * kopyasıdır. O yüzden, parametrede yapılan aşağıdaki * değişiklik çağıran tarafta gözlemlenemez. */ değer += 10; } void main() { int a; int b; onArttır(a); // ← sol değer; referans olarak geçirilir onArttır(a + b); // ← sağ değer; kopyalanarak geçirilir }
Parametrenin gerçekte sol değer mi yoksa sağ değer mi olduğu static if
'i __traits(isRef)
ile kullanarak öğrenilebilir:
void onArttır()(auto ref int değer) { static if (__traits(isRef, değer)) { // 'değer' referans olarak geçirilmiş } else { // 'değer' kopyalanarak geçirilmiş } }
static if
'i ve __traits
'i daha sonra Koşullu Derleme bölümünde göreceğiz.
Terimler
"Sol değer" ve "sağ değer" anlamına gelen "lvalue" ve "rvalue" ne yazık ki bu iki çeşit değeri yeterince ifade edemez. Başlarındaki l ve r harfleri "sol" anlamındaki "left"ten ve "sağ" anlamındaki "right"tan gelir. Bu sözcükler atama işlecinin sol ve sağ tarafını ifade ederler:
- Değişmez olmadıkları sürece, sol değerler atama işlecinin sol tarafındaki ifade olarak kullanılabilirler.
- Sağ değerler atama işlecinin sol tarafındaki ifade olarak kullanılamazlar.
Bu terimlerin açık olmamalarının bir nedeni, hem sol değerlerin hem de sağ değerlerin aslında atama işlecinin her iki tarafında da yer alabilmeleridir:
/* Bir sağ değer olan 'a + b' solda,
* bir sol değer olan 'a' sağda: */
array[a + b] = a;