const
ve immutable
Kavramları
Çeviren: Ali Çehreli
Tarih: 13 Temmuz 2009
İngilizcesi: Const and Immutable
[Çevirenin notu: "constant" ve "immutable" sözcüklerinin hem İngilizce hem Türkçe karşılıkları temelde aynıdır: sabit, değişmez. Türkçe'de const
başka programlama dillerinde zaten "sabit" olarak geçtiği için ben burada da aynı karşılığı kullanıyorum. Böylece immutable
'a "değişmez" kalıyor.]
Bir veri yapısını veya bir arayüz fonksiyonunu incelerken hangi verilerin değişmeyeceklerini, hangilerinin değişebileceklerini, ve değişimlerin kimin tarafından yapılabileceğini bilmek çok önemlidir. Bunu sağlayan düzeneklerden birisi, dilin tür sistemidir. D'de her veri const
veya immutable
olarak belirtilebilir. Özellikle belirtilmemişse veri değişebilir demektir.
immutable
, verinin değişemez olduğunu bildirir. Bu tür veriler, ilk değerlerini aldıktan programın sonuna kadar aynı değerde kalırlar. Bunlar ROM'a veya donanımın değiştirilemez olarak işaretlediği bellek bölgelerine yerleştirilmiş olabilirler. Verinin değişemez olduğunun baştan biliniyor olması; derleyici için eniyileme olanaklarının artmasının yanında, fonksiyonel programlama açısından da yararlıdır.
const
, verinin const
olarak belirlenen referans yoluyla değiştirilemeyeceğini bildirir. Aynı veri, başka bir referans aracılığıyla değiştirilebilir durumda olabilir. const
, fonksiyonların verileri değiştirmeyecekleri sözü vermeleri için kullanılır.
const
ve immutable
geçişlidirler; onlar aracılığıyla erişilen başka veriler de yine const
veya immutable
'dırlar.
immutable
depolama türü
immutable
'ın en basit kullanımı sabit değerler oluşturmaktır.
immutable int x = 3; // x 3'tür x = 4; // hata: x değiştirilemez char[x] s; // s, uzunluğu 3 olan bir char dizisidir
Verinin türü, ilkleme için kullanılan değerden çıkarsanabilir:
immutable y = 4; // y'nin türü int'tir y = 5; // hata: y değiştirilemez
Eğer ilkleme değeri henüz mevcut değilse, değişmez veri daha sonraki bir noktada kendisiyle ilgili kurucuda ilklenebilir.
immutable int z; void deneme() { z = 3; // hata: z değiştirilemez } static this() { z = 3; // olur: ilkleme değeri z'nin tanımlandığı // noktada bilinmiyorsa burada ilklenir }
Yerel olmayan bir immutable
verinin ilk değerinin derleme zamanında hesaplanabilen bir türden olması gerekir.
int foo(int f) { return f * 3; } int i = 5; immutable x = 3 * 4; // olur: 12 immutable y = i + 1; // hata: derleme zamanında işletilmez immutable z = foo(2) + 1; // olur: foo(2) derleme zamanında 7 // olarak hesaplanır
static
olmayan yerel immutable
veriler çalışma zamanında ilklenirler.
int foo(int f) { immutable x = f + 1; // çalışma zamanında işletilir x = 3; // hata: x değiştirilemez }
Değişmezlik geçişli olduğu için immutable
yoluyla erişilen veri de değişmezdir.
immutable char[] s = "foo"; s[0] = 'a'; // hata: s bir immutable veri referansıdır s = "bar"; // hata: s değiştirilemez
immutable
veriler soldeğerlerdir [lvalue]. Yani adresleri alınabilir ve bellekte yer tutarlar.
const
depolama türü
const
bildirimi ile immutable
bildirimi arasında şunlardan başka fark yoktur:
- Veri,
const
olarak bildirilmiş referansı yoluyla değiştirilemez, ama aynı vericonst
olmayan başka bir referans yoluyla değiştirilebilir. const
bildiriminin kendi türü deconst
'tır.
immutable
türler
Değeri değişmeyecek olan verilerin türleri immutable
olarak bildirilebilir. immutable
anahtar sözcüğü bir tür kurucusu olarak düşünülebilir:
immutable(char)[] s = "merhaba";
immutable
anahtar sözcüğü, o kullanımda parantez içindeki türü etkiler. Orada s
'ye yeni değerler atanabiliyor olsa da, s
'nin içindeki değerler değiştirilemez:
s[0] = 'b'; // hata: s[] değiştirilemez s = null; // olur: s'nin kendisi immutable değil
immutable
geçişlidir; kendisi yoluyla erişilen veri de değiştirilemez:
immutable(char*)** p = ...; p = ...; // olur: p immutable değil *p = ...; // olur: *p immutable değil **p = ...; // hata: **p değiştirilemez ***p = ...; // hata: ***p değiştirilemez
Depolama türü olarak kullanılan immutable
, bütün bildirimin türü için kullanılan tür kurucusu immutable
'ın eşdeğeridir:
immutable int x = 3; // x'in türü immutable(int) olur immutable(int) y = 3; // y değiştirilemez
Değiştirilemeyen veri oluşturmak
Bunun bir yolu, değiştirilemeyen değerler kullanmaktır. Örneğin dizgi sabitleri değiştirilemezler:
auto s = "merhaba"; // s'nin türü immutable(char)[] olur char[] p = "dünya"; // hata: immutable, değiştirilebilen bir // türe otomatik olarak dönüşemez
Diğer yol, tür değişiminde immutable
kullanmaktır. Ama böyle yapıldığında, veriyi değiştirebilecek başka referansların bulunmadığını sağlamak programcının sorumluluğundadır.
char[] s = ...; immutable(char)[] p = cast(immutable)s; // tanımsız davranış immutable(char)[] p = cast(immutable)s.dup; // olur: p, .dup ile kopyalanan yeni kopyanın tek referansıdır
Dizilerin immutable
kopyalarını almanın kolay yolu, .idup
dizi niteliğini kullanmaktır:
auto p = s.idup; p[0] = ...; // hata: p[] değiştirilemez
immutable
'ın tür değişimi ile kaldırılması
Değişmezlik tür dönüşümü ile kaldırılabilir:
immutable int* p = ...; int* q = cast(int*)p;
Ama bu, verinin artık değiştirilebileceği anlamına gelmez:
*q = 3; // derleyici izin verir ama tanımsız davranıştır
Bazı durumlarda immutable
'ın kaldırılabilmesi gerekebilir. Örneğin kaynak kodlarına sahip olmadığımız bir kütüphane, immutable
olması gereken fonksiyon parametrelerini immutable
olarak bildirmemiş olabilir. O kütüphane fonksiyonlarını çağırabilmek için immutable
'ı tür dönüşümü yoluyla kaldırmak zorunda kalırız; ancak bu durumda sorumluluk tamamen programcıya aittir; derleyici o veri için artık denetim sağlayamaz.
immutable
üye fonksiyonlar
Üye fonksiyonları immutable
olarak bildirmek, o nesnenin o üye fonksiyon içindeyken değiştirilemeyeceği anlamına gelir. Bu, nesne içinde tanımlı bütün verileri ve onların this
yoluyla erişildiği durumları kapsar:
struct S { int x; immutable void foo() { x = 4; // hata: x değiştirilemez this.x = 4; // hata: x değiştirilemez } }
const
ve immutable
belirteçleri üye fonksiyonların parametre listesinden sonra da yazılabilirler:
struct S { void bar() immutable { } }
const
türler
const
türler de immutable
türler gibidirler; ama bu türden olan veriler const
olmayan referanslar yoluyla değiştirilebilirler.
const
üye fonksiyonlar
const
üye fonksiyonlar içindeyken nesnenin this
yoluyla erişilen üyeleri değiştirilemez.
Otomatik dönüşümler
Değişken (normal) türler ve immutable
türler otomatik olarak const
'a dönüşürler. Değişken türler immutable
türlere, immutable
türler de değişken türlere otomatik olarak dönüşmezler.
D'deki const
ve immutable
'ın C++'daki const
ile karşılaştırılması
Olanak | D | C++98 |
---|---|---|
const anahtar sözcüğü | var | var |
immutable anahtar sözcüğü | var | yok |
const yazımı | Fonksiyon bildirimi gibi:
// const int // const işaretçisi // işaretçisi: const(int*)* p; |
Sonda:
// const int // const işaretçisi // işaretçisi: const int *const *p; |
const geçişliliği | var:
// const int // const işaretçisi // const işaretçisi: const int** p; **p = 3; // hata |
yok:
// int // işaretçisi // const işaretçisi: int** const p; **p = 3; // olur |
const'ı kaldırmak | var:
// const int işaretçisi: const(int)* p; int* q = cast(int*)p; //olur |
var:
// const int işaretçisi: const int* p; int* q = const_cast<int*>p; // olur |
const'ı kaldırdıktan sonra değişiklik | yok:
// const int işaretçisi: const(int)* p; int* q = cast(int*)p; *q = 3; // tanımsız davranış |
var:
// const int işaretçisi: const int* p; int* q = const_cast<int*>p; *q = 3; // olur |
fonksiyon yüklemede üst düzey const'ın etkisi | var:
void foo(int x); void foo(const int x);//olur |
yok:
void foo(int x); void foo(const int x);//hata |
aynı const'a değişken olarak da erişebilmek | var:
void foo(const int* x, int* y) { bar(*x); // bar(3) *y = 4; bar(*x); // bar(4) } ... int i = 3; foo(&i, &i); |
var:
void foo(const int* x, int* y) { bar(*x); // bar(3) *y = 4; bar(*x); // bar(4) } ... int i = 3; foo(&i, &i); |
aynı immutable'a değişken olarak da erişebilmek | yok:
void foo(immutable int* x, int* y) { bar(*x);// bar(3) *y = 4; // tanımsız // davranış bar(*x);// bar(??) } ... int i = 3; foo(cast(immutable)&i, &i); |
immutable desteklenmez |
dizgi sabitlerinin türü |
immutable(char)[] |
const char[N] |
dizgi sabitinin değişken dizgiye otomatik dönüşümü | izin verilmez | izin verilir ama emekliye ayrılmış [deprecated] bir olanaktır |