Rust programming language introduction book for Turkish developers.
It is just the first version, so it will be updated during the development of Rust.
Mahmut Bulut
=================
Bu kitap Rust programlama diline basit bir giriş olması niteliğinde yazıldı, dilin kul-
lanımını arttırmak ve Türk geliştiricilere/kullanıcılara dili tanıtmak amacı güt-
mektedir. Rust şu anda prototip seviyesinde olduğundan; keskinleştirilmiş ve
yapının iskeletini oluşturan kısımları buraya aldım. Dilin daha üzerinde tartışılan
ve gelecek versiyonlarında yer alacak tüm semantik ve sentaks yapısı bu kitabın
içeriğinde değildir. Rust’ın derin semantik yapısına ve çekirdek ilkelerine değinerek
okuyucu zorlamak istemediğimden basit ve sade, günlük hayatta kullanılabilecek
cinsten örnekler vermeye önem verdim. Kitap Rust’a yeni başlayanlar ve ilgi duy-
anlar için birebirdir. Ayrıca bu kitap Rust programlama dilinin yazıldığı zamana
ait Türkçe dökümantasyonu olma özelliğini de taşır. Türkçe bilişim terminolojisine
girmeyen ama yeni tanımlanmış bazı terimleri de Türkçeye kazandırmak amacı
da gütmektedir.
3. Mahmut BULUT, Eskişehir Osmangazi Üniversitesi Bilgisayar Mühendisliği
bölümünde öğrenimini sürdürmektedir. Yapay zeka ve topluluk zekası konusunda
çalışmalar yapmaktadır, Haskell’in Hackage veritabanında Planlama ve MAS
sistem desteği üzerinde çalışmaktadır. Mageia Linux dağıtımının QA sorum-lusudur.
2012 yılı itibariyle Rust programlama dilinin oluşturulmasında rol almıştır
ve ana geliştiricilerinden biridir. Özel bir şirkette çalışmasına devam etmekte ve
Rust programlama dilini de geliştirmektedir.
ii
4. Önsöz
Bu kitap Rust programlama diline basit bir giriş olması niteliğinde yazıldı, dilin kul-lanımını
arttırmak ve Türk geliştiricilere/kullanıcılara dili tanıtmak amacı güt-mektedir.
Rust şu anda prototip seviyesinde olduğundan; keskinleştirilmiş ve
yapının iskeletini oluşturan kısımları buraya aldım. Dilin daha üzerinde tartışılan
ve gelecek versiyonlarında yer alacak tüm semantik ve sentaks yapısı bu kitabın
içeriğinde değildir. Rust’ın derin semantik yapısına ve çekirdek ilkelerine değinerek
okuyucu zorlamak istemediğimden basit ve sade, günlük hayatta kullanılabilecek
cinsten örnekler vermeye önem verdim. Kitap Rust’a yeni başlayanlar ve ilgi duy-anlar
için birebirdir. Ayrıca bu kitap Rust programlama dilinin yazıldığı zamana
ait Türkçe dökümantasyonu olma özelliğini de taşır. Türkçe bilişim terminolojisine
girmeyen ama yeni tanımlanmış bazı terimleri de Türkçeye kazandırmak amacı
da gütmektedir.
iii
6. İçindekiler
1- Rust’a Genel Bakış 6
1.1- Kitap Konvansiyonları 6
1.2- Nedenler ve Amaçlar 6
1.3- Özellikler 6
2- Rust’ın Temelleri 8
2.1- Kurulum 8
2.1.1- Parçalar ve İnşaa Sistemi Önbilgisi 8
2.1.2- İşletim Sistemine Kurulum 8
2.1.3- Editör ve Geliştirme Ortamları 10
2.2- İlk Adımlar 10
2.3- Değişkenler 11
2.3.1- Immutable(Değişmez) Değişkenler 11
2.3.2- Mutable(Değişen) Değişkenler 12
2.3.3- Tip Tanımlamaları 12
2.3.4- İfade Yapısı/Sentaks 13
2.4- Veri Tipleri 17
2.4.1- Literaller 19
2.4.2- Sabitler 19
2.4.3- Operatörler 19
2.4.4- Sentaks Genişletmeleri 20
3- Program Akışı 21
3.1- Kontrol Yapıları 21
3.1.1- Koşullu Yapılar 21
3.1.2- Örnek Eşleme 22
3.1.3- Döngüler 23
3.2- Veri Yapıları 24
3.2.1- Struct 24
3.2.2- Enumeration 25
3.2.3- Tuple 26
v
7. BÖLÜM 1
Rust’a Genel Bakış
Kitap Konvansiyonları
Bu kitapta mümkün olduğunca basit ve anlaşılır bir konvansiyon kullanmak iste-dim.
Bundan dolayı sadece kodlar, uyarılar ve örnekler yer alacak.
Kodların ve komutların yazım stili ise ”bu şekilde” olacaktır.
Uyarıların yazım stili italik olacak şekildedir. Örnekler ve kod parçacıkları(snip-pets)
yine kod konvansiyonu şeklinde yazılacaktır.
Nedenler ve Amaçlar
Şuana kadar geliştirilen hiçbir programlama dili bize tam manalı paralelizm,
statik tip tanımlamasında kesinlik, hafıza yönetiminde ve performansta güçlülük
sağlamadı. Bunu yapan diller çok az olduğu gibi ata olan C bize tip tanımlama-larında
zorluk ve hafıza yönetiminde güç kaybı yaşattı. Günümüzde meşhur olan
scripting dillerine rağmen derlenebilir ve her ortamda çalışabilmesi öngörülen
diğer derlenebilir dillerden farklı, komplex akışların uygulanabildiği dillere ihtiyaç
duyuldu. Bu dillere örnek olarak Haskell ve OCaml verilebilir fakat bu diller alt-seviye
dillerle aralarında soyut bir ayrım olduğu için düşük seviyeye yakın program
yazımını zorlaştırıyordu. Bu zorluğu çözebilmek adına C ve C++’ın özelliklerin-den
de alınması ve harmanlanması gerekiyordu. Mozilla Arge’si tüm bunların so-nucunda
bütün iyi özellikleri alan bir programlama dili olan Rust’ı ortaya çıkardı.
Özellikler
Rust esnektir. En belirgin özelliklerinden biri de bu özelliğidir. Esnekliğin sebebi
tip tanımlamalarının zorunlu olmamasıdır. Tipleri keskinleştirip yumuşatmak ve
birbirlerine çevrimini sağlamak sizin elinizdedir. Belirtilen her tip tanımlaması ke-
6
8. skin tipi oluşturup dönüşümünü zor hale getirirken, belirtilmeyen tipler aynı isimli
başka değişkenlerin oluşumuna engel olmaktadır. Bu iyi birşeydir ve aynı ada sahip
iki tane farklı değişken oluşturabilmenize olanak sağlar.
Rust aynı zamanda paralelizme önem verir, mesaj aktarımı yoluyla paralel
çalışmayı destekler bu hafif ve işlemci yormayan bir sistemdir. Diğer bellek pay-laşımlı
çalışan sistemlere nazaran daha iyi bir performansı da beraberinde getirir.
Başta da belirttiğimiz gibi yüksek seviyeli programlama dillerinden örnek
alınan kompleks sistem dizaynına olanak sağlayan dereceli fonksiyon tanımlama-larına
izin verir. Bu Haskell ve Ocaml’ın da bir özelliğidir.
C’deki struct, enum ve typedef kalıplarını daha da güçlendirerek sunar.
Rust birçok programlama dilinin uygulama biçimlerini de kendine dahil et-miştir,
örnek olarak:
• Go programlama dilinden yığın büyüme algoritması
• SML’in veri yapıları
• C#‘ın makine kodu oluşturma ve birleştirme sekansı
• C++’ın hafıza referanslama ve destructor özelliği
• Cyclone ve ML Kit’in hafıza belirleme ve sızıntı önleme sistemleri
• Haskell’in tip sınıfları ve dönüşüm sistemleri
• Python’ın lexer sistemi
• Ruby’nin blok sentaksı (parantezlemesiz sistem)
Rust tamamıyla orijinal bir dil değildir bunun nedeni tüm dillerin en güçlü özel-liklerini
alarak arındırılmış sentaksı ile tüm işleri başarabilen bir sisteme evrilme
amacında olmasıdır. Rust gelecek senelerde en güçlü ve en kolay programlama dili
olma, sistem kontrolü, paralelizm ve hata toleranslı sistemlerin çekirdeğinde rol ala-cak
bir aracı olma misyonunu yüklenerek en iyi yere gelmeyi planlamaktadır.
7
9. BÖLÜM 2
Rust’ın Temelleri
Kurulum
Parçalar ve İnşaa Sistemi Önbilgisi
Kurulum üç çalıştırılabilir ve kütüphanelerden oluşmaktadır. Bunlar:
• rustc (Rust Derleyicisi)
• rustdoc (Rust Dokümantasyon Oluşturucu)
• cargo (Rust Paket Yöneticisi)
• librustllvm, librustrt, libcore, libstd, librustc, libsyntax ve libmorestack
kütüphaneleri (sistem oluşturulurken kullanılan diğer kütüphaneler önceden
yazılmış açık kaynak kütüphanelerdir)
İnşaa sistemi 3 fazdan oluşmaktadır her bir derleyici fazı kendinden sonraki der-leyici
fazını yapacak şekilde düzenlenmiştir. Faz.3 derleyicisi son derleyiciyi
yaptığında(kendini) Faz.2 ile birebir aynı bir imaj oluşturur(kendini yapan ile).
Bütün bu işlemlere ön-ayak olan ise bir önceki rust derleyicisi versiyonun son der-leyicisidir.
Bu derleyici yeni sistemin Faz.0‘ıdır.
İşletim Sistemine Kurulum
•Windows
Eğer Windows kullanıyorsanız sisteminize sırasıyla
• MinGW ve MSYS paketi (versiyon numarası 20110802 olmak üzere)
• MsysGit (Kurduktan sonra MinGW kurulum dizinindeki .bashrc dosy-asına
aşağıdaki satırı ekleyin
8
10. export PATH=$PATH:/c/Program Files/Git/bin
ve kaydedin.
• libpthread kütüphanesini kurun versiyon numarası 2.8.0-3
(libpthread-2.8.0-3-mingw32-dll-2.tar.lzma)
tüm bu yazılımları sisteminize kurduktan sonra http://www.rust-lang.org/ ad-resindeki
yükleyici’yi indirmelisiniz. Bu paket hazır derlenmiş ve kullanıma hazır
win32 çalıştırılabilirlerini ve kütüphanelerini içermektedir. Kurulum sırasında
PATH ortam değişkenine Rust’ı ekle seçeneğinin işaretli olduğundan emin olun.
Kurulum tamamlandığında artık Rust’ı kullanabilir durumda olacaksınız.
•*NIX türevleri ve Linux
Eğer *NIX türevi (buna MacOS’da dahil olmak üzere) veya Linux dağıtımların-dan
birini kullanıyorsanız
• g++ 4.4 veya clang++ 3.x serisi
• python 2.6 veya sonraki bir sürüm (fakat 3.x serisi olmamak kaydı ile)
• perl 5.0 veya daha sonraki bir sürüm
• gnu make 3.81 veya daha sonraki bir sürüm
• curl
yazılımlarının sisteminizde yüklü olduğundan emin olun. Tüm bu gereksinimler-den
emin olduktan sonra Rust’ı derlemek şu şekildedir:
$ wget http://dl.rust-lang.org/dist/rust-0.4.tar.gz
$ tar -xzf rust-0.4.tar.gz
$ cd rust-0.4
$ ./configure
$ make && make install
Benim yazdığım zamanda Rust derleyicisinin versiyonu 0.4’tü, şimdi yenilenmiş
olabilir güncel kaynak kodu yine Rust’ın kendi sitesinde bulabilirsiniz.
9
11. Editör ve Geliştirme Ortamları
Rust kodu yazabilmek için çeşitli editörler ve destekler mevcuttur. Bunlara ör-nek
vermek gerekirse Eclipse geliştirme ortamı, TextMate editörü, Vim ve Emacs
editörleri verilebilir.
• TextMate için destek paketi: Rust.tmbundle
• Eclipse plugin desteği: Oxide
• Emacs ve Vim için destek ise rust’ın kendi kaynak kodunda src/etc dizini
altında bulunmaktadır.
• Sublime Text 2 için Sublime Package Manager yoluyla Rust desteği yüklene-bilir.
• KDE’nin editörü Kate için ise yine kaynak kodun src/etc/kate dizini altında
desteğini bulabilirsiniz.
Rust daha çok yeni bir dil olduğundan dolayı tam anlamıyla bağımsız bir IDE
geliştirilmedi. Şimdilik elimizdeki editör ve destek miktarının bu kadar olduğunu
belirtmekle yetinelim. Geliştirmeler oldukça kitabın yeni revizyonlarında bunları
belirteceğim.
İlk Adımlar
Rust genel olarak veri yapılarında C’den farklı değildir, tiplerin tamamı C’nin
birebir kopyasıdır fakat bazı tipler üzerinde fazlaca çalışılmış ayrıca başka tiplerde
ekleme yapılmıştır, Rust’ı anlatırken çoğu zaman C ile karşılaştıracağız. Rust pro-gramları
.rs dosya uzantısını kullanırlar, .rc uzantısı ise Crate denilen bağımsız
derleme birimlerinin özelliklerini belirten dosyalardır. Şimdilik bunlara değinme-den
sadece bir dosyadan oluşan çalıştırılabilirleri anlatacağız.
İlk programımız klasik bir Merhaba Dünya olup helloworld.rs isimli bir
dosya açarak:
fn main() {
io::println("Merhaba Dünya! Rust’a hoşgeldin!");
}
10
12. metnini kaydediyoruz. Rust derleyicisini sisteminize başarı ile yüklediyseniz
rustc helloworld.rs
komutunu verdiğinizde size eğer *nix sistem üzerinde iseniz helloworld isimli
bir çalıştırılabilir oluşturulacaktır(eğer windows üzerinde iseniz bu çalıştırılabilirin
adı helloworld.exe olur). Çalıştırdığınızda ise
Merhaba Dünya! Rust’a hoşgeldin!
çıktısını alırsınız. Rust eğer çalıştırılabilir oluşturulacaksa C’deki gibi bir main
fonksiyonuna ihtiyaç duyar, aynı zamanda eğer kütüphanelerinde bulunmayan bir
fonksiyonla karşılaşırsa hata mesajını en dar şekilde vererek deterministik bir hata
çıktısı verir. Şimdi kodumuzu biraz değiştirerek şu hale getirelim
fn main() {
io::bu_satırı_bas("Merhaba Dünya! Rust’a
hoşgeldin!");
}
derleyip çalıştırdığımızda ise karşımıza şu mesaj çıkacaktır
helloworld.rs:2:4: 2:21 error: unresolved name: io::bu_satırı_bas
helloworld.rs:2 io::bu_satırı_bas("Merhaba Dünya! Rust’a hoşgeldin!");
"" ^~~~~~~~~~~~~~~~~
error: aborting due to previous error
Bu hatanın sebebi ise bu_satırı_bas isimli bir fonksiyonun olmamasıdır.
Değişkenler
Rust’ta değişkenler başta bahsettiğimiz gibi tip tanımlamasına bağlı şekilde ad-landırılıp
hafızada yer edinirler. Rust’ta değişkenler iki tiptir mutable(değişebilen)
ve immutable(değişmeyen) değişkenler.
Immutable(Değişmez) Değişkenler
Eğer tipini Rust’ın belirlemesini istediğiniz ve değişmez olmasını istediğiniz bir
değişken varsa tanımlama şu şekildedir:
11
13. let merhaba = "merhabalar"
Rust’ta değişkenler varsayılan olarak manipüle edilemez haldedir. Nasıl oluyor da değişken
oluyorlar? sorusunun cevabı ise dilin oluşturulma amacına bir referans niteliğinde-dir
Güvenli thread oluşumu(Thread-safe) özelliği bu yetenekten ileri gelir.
Mutable(Değişen) Değişkenler
Tanımlandıklarında C’deki herhangi bir sıradan lokal değişkenden pek farkları
yoktur. Şu şekilde tanımlanırlar:
let mut toplam = 0;
görüldüğü üzere mut keyword’ü değişkenin mutable olacağını ve değişebilir
şekilde yaratılması gerektiğini belirtmekte kullanılır. Mutable değişkenlerin kul-lanımına
bir örnek vermek gerekirse şöyle bir örnek verebiliriz:
fn main() {
let mut çevrim = 0;
"while (çevrim <= 10){
"" io::println("harika");
"" çevrim+=1;
"}
}
Tip Tanımlamaları
Tip tanımlamalarında tip ise C’deki gibi başta prefix (önek şeklinde) belirtil-mez.
Bunun yerine ikinoktadan sonra belirtilir. Örnek olarak;
let karpuz: float = 57.8;
let kavun = karpuz * 10.0;
let karpuz: int = 50;
io::println(fmt!("%d", monster_size));
12
14. İlk değişken olan karpuz kavun’u oluşturmak için kullanılmıştır. Görevi bittik-ten
sonra yeniden farklı bir tip ile yaratılabilir. Ama bu kodu derlediğimizde bize
kavun ve karpuz’u kullanmadığımızı söyleyen bir uyarı gelecektir. Bu bize son kar-puzu(
integer olarak deklare ettiğimiz) bir işlemde kullanmadığımızı ve immutable
olarak oluşturduğumuz kavun’u da bir işleme sokmadığımızı söylemektedir. Bu
uyarıdan kurtulmak adına kullanmadığınız değişkenlerin başına “_” koymanız ye-terlidir.
Rust’ta tanımlayıcılar C’deki gibi alfabetik karakter veya alttan çizgi ile başlar-lar
ve yine C’deki gibi numaralar, alfabetik karakterler ve alttan çizgi kombinasyon-ları
ile devam edebilirler. Rust’ta tanımlayıcı yazım konvansiyonu ilk harfin küçük ol-ması
ve gerekli yerlerde(kelimeler arasında vb.) alttan çizgi kullanılması üzerinedir. Ör-nek
olarak:
let yakışıklı_değişken = 100;
verilebilir. Fakat yeni tip tanımlamaları bu konvansiyonu kullanmaz, bunun yerine
camelCasing dediğimiz ilk harfi küçük sonraki her kelimenin ilk harfi büyük olma
koşuluna uyarlar, örnek bir yeni tip tanımlaması ise şu şekildedir:
type yeniBirTipTanımlaması = int;
Rust’ta kod yazarken Türkçe karakter kullanabilirsiniz. Bu size taşınabilirlikte
de kullanılabilirlikte de sorun çıkarmaz.
İfade Yapısı/Sentaks
Rust kendisi değer döndürebilen ve değeri yerleştirebilen bir yapıya sahiptir. Bu
yapı tanımlayıcıların tekrar tekrar kullanılmasını önlemekle beraber return key-word’ünde
bile blok yazmamızı da sağlamaktadır. Şimdi C’deki bir yapıyı Rust’ta
gösterelim.
let şeker;
if item == "reçel" {
şeker = 3.50;
} else if item == "kek" {
13
15. şeker = 2.25;
} else {
şeker = 2.00;
}
Bu stil C’deki tanımlamanın birebir uyarlamasıdır. Bunun yerine biz Rust’ta bu
yapıyı yazmak istesek daha güzel ve mantıksal bir yol izleyerek;
let şeker =
if item == "reçel" {
3.50
} else if item == "kek" {
2.25
} else {
2.00
};
bu şekilde tanımlayacaktık. Bu bize sadece atamayı değil aynı zamanda içeride so-nucu
oluşturabilecek bir fonksiyonu da kullanabilmemizi sağlıyor. Dikkat ettiyseniz
2. örnekte noktalıvirgül sözkonusu değildir son bloktaki noktalı virgül tüm blok zin-cirinin
başlıbaşına bir kod olarak çalıştırılmasını tetikler, bu bize esneklikte sağlar
aynı zamanda örnek olarak 3.50 değeri yerine 3.50 değerini oluşturan bir fonksiyo-nun
varolabilmesi hatta bu fonksiyonun diğer durumlara da bağlı olabilen tek para-metreli
bir fonksiyon da olabilmesi gibi. Rust işte bu şekilde bizim yapabilecek-lerimizi
esneterek ve kısaltarak kolaylık sağlamaktadır. Aynı zamanda Rust işlemci
üzerindeki boş işlemci vaktini paralel threadler çalıştırarak minimize etmektedir.
Yukarıdaki örnekte 3.50, 2.25 ve 2.00 olarak değer atadığımız satırlar eğer “;”
ile kullanılsalardı, ifade mekanizması çalışmayacaktı. Bunun nedeni bahsettiğimiz
bloklamadır. Böyle bir atama yine de çalışır fakat atanma değişkene döndürülüy-orsa
nil fonksiyona döndürülüyorsa void olur. Bu da istediğimiz sonucu vermez.
14
16. Değişkenler için let, fonksiyonlar için fn , trait tanımlamaları, enumlar
ve constantlar harici dil dahilinde kalan herşey ifade kapsamına girmektedir.
Rust’ta ifade olması için fonksiyon içeriği olmak bile yeterlidir. Örneğin;
fn dört_döndür(x: int) -> bool {
x==4
}
return ifadesine gerek duyulmadan alınan değer return değeri amacıyla kullanıla-caktır.
Eğer satırlar atama, binary veya unary operasyonlar için kullanılmıyor ve fonksi-yonlar
kullanılıyorsa;
let x = foo();
if x {
bar();
} else {
baz();
}
Bu şekilde fonksiyon sonrası “;” ifadesi kullanılarak yazılırlar. Burada önemli olan
şu noktadır: eğer biz bu fonksiyonlardan bir değer döndürmüyorsak ve fonksiyon-larımız
C’deki void fonksiyonlar gibi ise(ki bu Rust’ta nil-type’a karşılık gelir) her
ifade çevriminin sonuna yukarıda belirttiğimiz gibi bir “;” konulur.
Bu durumlar “;”ün konulduğu durumlardır. Konulmadığı durumların genel
özelliği ise kesin bir değer döndürüp bu değer’in nil’den farklı olduğu durumlar ol-maktadır.
İşte buna bir örnek ise:
fn bar() -> int {
"let a = 9;
"return a;
15
17. }
fn baz() -> int {
"return 10;
}
fn main() {
"let x = false;
"io::println(fmt!("Cevap %d",
"if x {
"bar()
"} else {
"baz()
"}));
}
Görüldüğü üzere bar() ve baz() değer döndürdükleri için “;” koymuyoruz hatta
blok sonuna da koymamamızın nedeni println()’in onu hesaplama girişiminde bu-lunacağıdır.
16
18. Veri Tipleri
Tipler genel olarak C’deki gibidirler ve şu şekilde gösterilebilirler:
Tipler Açıklama
() Bir tek değer içeren, Birim
bool true veya false değerlerine sahip olan,
Kompozit tipler de genel yapıları itibariyle aşağıdaki şekildedir. Burada her T
bir başka tipi göstermektedir.
Bazı tipler hiçbir zaman pointer olmadan değiştirilemezler. Örneğin string ola-rak
tanımlanmış değerlere ~, @ ve & işaretçilerinden biri kullanılmadan erişim
yapılamaz. Bu kullanıma sahip olan tipler genellikle dinamik genişleyebilen(karak-ter,
saf veri vb. ile) tiplerdir.
17
Boolean
int, uint
Üzerinde çalıştığı makinenin
tanımlamalarına bağlı işaretli ve işaretsiz
tamsayılar, signed & unsigned integer
i8, i16, i32, i64 Belirli bit büyüklüğünde işaretli tamsayılar,
signed sized integers
u8, u16, u32, u64 Belirli bit büyüklüğünde işaretsiz
tamsayılar, unsigned sized integers
float
Üzerinde çalıştığı makinenin üzerinde
genel konvansiyonda en iyi çalışabilecek
en büyük ondalıklı sayı, float
f32, f64 Belirli bit büyüklüğünde ondalıklı sayılar,
floating type
char Unicode karakter setini kullanan karakter
(32 bit)
Kompozit Tipler Açıklama
[T * N] Vektör (Vektör diğer dillerdeki diziyi
temsil eder)
[mut T * N] Mutable vektör
(T1, T2) Tuple tipleri
&T, ~T, @T Pointer tipleri
19. Dinamik genişleyen tiplere ise şu örnekleri verebiliriz:
Dinamik Genişleyen Tipler Açıklama
fn(a: T1, b: T2) -> T3 Fonksiyon tipleri
str String(Katar) tipleri (UTF-8)
[T] Uzunluğu bilinmeyen vektör (diğer adıyla
Fonksiyon tiplerinde değer döndürme -> işareti ile belirtilir fonksiyon deklerasy-onunda
ise şu şekildedir:
fn foo() -> bool { }
Rust’ın en güzel özelliklerinden biri de anlamsız veya işinize yaramayan bir değer
döndürmeniz gerektiğinde -> () şeklinde bir yazım yapabilmenizdir. Bunun
yanında bu yazım yapılmasa da olur.
Yeni tip tanımlamaları takmaad olarak da kullanılabilir ve şu şekilde tanım-lanır:
type BüyükVeri = uint;
Bu tanımlama BüyükVeri tipiyle uint tipini aynı bağlamda kullanabiliriz. Burada
önemli olan kısım bu tanımlamada BüyükVeri ve uint tiplerinin birbirinden bağımsız olduk-larını
sanıp dönüştürülemeyeceğini düşünmektir, fakat durum böyle değildir veriler birbirl-erine
dönüştürülebilirler çünkü tipler saklanırken yapılarına göre saklanır
BüyükVeri’nin özünde uint olduğu bilinmektedir.
Rust’ta tiplerimizin ismen bağlanmasını ve yapısallıkla ilişki kurmamasını istiy-orsak
struct ve enum anahtar kelimelerini kullanabiliriz.
18
dilim)
[mut T] Uzunluğu bilinmeyen mutable vektör
20. Literaller
Integerlar(tamsayı) decimal, hexadecimal veya binary formatlarda yazılabilirler.
Bu yazımların tamamına integral tip denir. Tüm integral tipler son ek’e sahiptir ve
literalin çeşidini belirler. int için i, uint için u, int8 için i8 tipi gibi.
Literaller konulmazsa Rust fonksiyon argümanları ve tip tanımlamalarıyla lit-eral
olmaksızın tanımlamayı tahmin eder ve ona göre yorumlar genellikle bu yo-rumlama
sisteme en yakın varsayılan üzerinedir. Örnek olarak;
let a = 1; // a varsayılan olarak int atanır
let b = 10i; // b int oldu, i son ekinden dolayı
let c = 100u; // c uint oldu
let d = 1000i32;
verilebilir.
Sabitler
Derleme zamanı sabitleri const anahtar kelimesi ile tanımlanır.
const PAROLAM: int = 12345;
const KATAR_PAROLAM: &static/str = "12345";
const EV_PAROLAM: int = PAROLAM + 1;
Operatörler
Aritmetik operatörler
*, /, %, +, - (çarp, böl, mod al, topla, çıkar) ayrıca - unary operatör
olup sayıları negatif yapmakta kullanılır. C’deki gibi bit operatörleri >>, <<, &, |,
ve ^ ‘dir.
! tüm bitleri ters çevirir ve C’deki ~ operatörü gibi.Rust’ın karşılaştırma oper-atörleri
C’deki karşılaştırma operatörleriyle aynıdır.
== , !=, <, >, <=, >=, &&, || gibi...
19
21. Tip dönüşümü yaparken Rust as operatörünü kullanır. Örnek olarak
let x: float = 4.0;
let y: uint = x as uint;
assert y == 4u;
Sentaks Genişletmeleri
Dilin saf haline entegre olmamış ama sonradan kütüphaneler yardımıyla dahil
edilmiş özelliklerdir. Şu anda std::core kütüphanesi bu genişletmeleri yeterli
miktarda karşılamaktadır. C formatlamasının benzer özellikleri kütüphaneler
yardımıyla alınmıştır. Katar formatlamanın geliştirilmesi gündemdedir.
io::println(fmt!("%s bence %d", "cevap", 43));
io::println(fmt!("Bu nedir %?", gizli_nesne));
Yukarıdaki örneğimizde %? tüm tipleri içine alabilen ve manipüle ederek for-mata
uyduran ibaredir. Dikkat ederseniz fmt!() olmadan formatlama yapılama-maktadır.
Bu fonksiyon çekirdek kütüphaneyi kullanarak formatlama yapacaksak
mecburidir. Kendi sentaks genişletmelerinizi de yazabilirsiniz. Rust buna izin verir.
Bu genişletmelerin genel adı makrolardır.
20
22. BÖLÜM 3
Program Akışı
Kontrol Yapıları
Koşullu Yapılar
If yapısını önceki bölümlerde gözden geçirdik kısa bir örnekle özetleyelim:
if false {
io::println("yanlış olan kısım");
} else if true {
io::println("doğru yer");
} else {
io::println("ne doğru ne yanlış");
}
Fakat eğer her blokta değer döndürülme mekanizması şeklinde çalışıyorsa if
yapısı tüm blok içlerindeki değerler kesinlikle aynı tipte olmak zorundadır. Örnek olarak:
fn signum(x: int) -> int {
if x < 0 { -1 }
else if x > 0 { 1 }
else { return 0 }
}
21
23. Örnek Eşleme
Rust örnek eşleme mekanizmasını diğer mekanizmalara tercih eder bundan do-layı
örnek eşleme mekanizması gelişmiştir. match mekanizması C’deki
switch’in bir benzeri olabileceği gibi return durumlarında döndürülecek seçe-neklerin
belirlenmesini sağlamaktadır.
match numara {
0 => io::println("sıfır"),
1 | 2 => io::println("bir veya iki"),
3..10 => io::println("3ten 10a kadar"),
_ => io::println("geri kalan tüm durumlar")
}
C’deki gibi bir case yapıldıktan sonra kaldığı yerden devam etmez. Bu yapı
sabittir ve sadece bir dalı yapar ve işlemini bitirir. ( _ ) wildcard eşlemesi olarak ad-landırılan
ifadedir ve anlamı “en az bir eşleşme”dir. ( * ) ise “enum tanımla-masında
bir veya daha fazla eşleşme” anlamına gelmektedir.
Kollar her zaman => işaretiyle tanımlanmasına başlanır.
match numara {
0 => { io::println("sıfır") }
_ => { io::println("başka birşey") }
}
numara değeri 0’a eşitse “sıfır” string’ini ekrana bastırırken diğer tüm girdi du-rumlarında
“başka birşey” çıktısını verecektir.
match tüm kolları arar ve tüm olası durumları koşul üzerinden geçirir.
match’in en önemli işlevlerinden biri değişken isimleri ile verilerin bağlanabilmesi-dir.
Aşağıdaki örnekte (veri1, veri2) tuple veritipine örnektir.
22
24. fn angle(vector: (float, float)) -> float {
let pi = float::consts::pi;
match vector {
(0f, y) if y < 0f => 1.5 * pi,
(0f, y) => 0.5 * pi,
(x, y) => float::atan(y / x)
}
}
Değişkenin ismi örnekteki veriyle eşlenmiştir. İlk kolda görülen ve y yazılan
yerde bulunan veri kontrol ve manipüle edilebilir. Aynı zamanda üçüncü koldaki
(x, y) örneği tamamen örnek eşlemeye yönelik bir tuple’dır. Her match kolu
if ile takip ediliyorsa bu if ifadesine örnek bekçisi denir. Örnek bekçisi ifadenin
doğruluğunu kontrol ettikten sonra koldaki ifadeyi yapmaya yönelir. İfade ister
değer döndürme olsun ister bir fn döndürme tipine bakılarak işlem yapılır, ne
olduğuna bakılmaz.
Döngüler
Rust’ta döngü yapımı sadece while ile sağlanabilir. Array kavramı vektör olarak
yer aldığı için vektör üzerinde iterasyon sadece bekçi içeren ifadeler ile yapılabilir.
For döngüsü Rust için gelecekte planlanan bir özelliktir. While döngüsü yine C’den
çok farklı olmamakla birlikte aşağıdaki gibidir:
let mut cake_amount = 8;
while cake_amount > 0 {
cake_amount -= 1;
}
Rust’ta while (true) ifadesi için geliştirilmiş özel bir sentaks vardır bu ifade
loop ‘tur. Sonsuz döngüyü ifade eder:
23
25. let mut x = 5;
loop {
x += x - 3;
if x % 5 == 0 { break; }
io::println(int::str(x));
}
Bu kod birkaç sayı yazdıktan sonra 5’e bölünebilen bir sayı bulduğunda sonsuz
döngüden çıkacak şekilde yazılmıştır.
Veri Yapıları
Struct
İlk olarak struct yapısıyla başlayabiliriz. Struct yapısı C’dekine benzer bir yapı
sergilemektedir hatta hafızada tutulma şekilleri aynıdır. Kullanımı C’deki kullanım
şekliyle aynıdır.
struct Stack {
content: ~[int],
mut head: uint
}
Yıkıcı sentaks bir değeri yerine tanımlanmış başka bir değişkenle manipüle etmektir. Daha önce
de bahsettiğimiz yıkıcı yapı structlar için de kullanılabilir. Örneğin;
match Noktam {
Nokta { x: 0.0, y: yy } => {
io::println(yy.to_str());}
Nokta { x: xx, y: yy } => {
io::println(xx.to_str() + " " + yy.to_str()); }
24
26. }
Enumeration
Enumlar birden fazla şekilde gösterilebilirler. En basit gösterimlerinden biri;
enum Şekil {
Daire(Point, float),
Dikdörtgen(Point, Point)
}
şeklindedir. Argüman olarak atama yapılabildiği gibi sıradan C enumları gibi
kendi içlerinde büyükten küçüğe indeks sıralaması yapan enumlar da vardır. Ör-nek
olarak:
enum Yön {
Kuzey,
Güney,
Doğu,
Batı
}
Kuzey 0, Güney 1, Doğu 2 ve Batı 3 değerini almaktadır. Fakat diğer atamalı
enumlarda bu tanımlama geçerli olmayıp her belirtme atamaya göre yapılır.
Dereferans(deref) işlemi de bir unary operatör olup enumlar üzerinde içerisin-deki
değeri almalarını sağlamaktadır.
enum Ses { Ses (int) }
let ses_seviyesi: Ses = Ses(10);
let anlık_ses_seviyesi: int = *ses_seviyesi;
Başka bir içerikten bilgi alınması bu şekilde sağlanabilir.
25
27. Enumlar aynı zamanda örnek eşlemede de kullanılabilirler:
fn bu_noktadan_tarif(dir: Yön) -> Nokta {
match dir {
Kuzey => Point {x: 0f, y: 1f},
Doğu => Point {x: 1f, y: 0f},
Güney => Point {x: 0f, y: -1f},
Batı => Point {x: -1f, y: 0f}
}
}
Tuple
Rust’ta tuplelar enumlar gibi çalışır dakat enumlar gibi alanadları yoktur.
Argümanlaştırma işlemi yapılır fakat bu işlemde 0 veya 1 argüman olarak verilemez. Enumda
bu yapılırken tuple da bu yapılamaz. Örnek bir tuple ise şu şekildedir:
let mytup: (int, int, float) = (10, 20, 30.0);
match mytup {
(a, b, c) => log(info, a + b + (c as int))
}
Rust’a dair 0.4 versiyonuyla kesinleşmiş ve temele oturmuş özellikler ve yapılar
bunlardır. Traitler, yeni döngüler, REPL(read evaluate print loop), Exception
mekanizması gibi özellikler yeni yeni geliştirilmektedir. Ayrıca fonksiyonların saflığı
ve saf olmamaları ve bu saflık yapısının nasıl olması gerektiği hakkında hala bir
takım belirlenmemiş kısımlar vardır.
26