Fonksiyonlar ve Kontrol Akışı
Fonksiyonlar
Fonksiyonlar fn
anahtar sözcüğü kullanılarak tanımlanırlar. Parametre aldıklarında ve geriye bir değer döndürdüklerinde tip ataması yapılmalıdır.
fn equals(first: u64, second: u64) -> bool {
first == second
}
fn main() {
equals(2,2); // true döndürür
equals(3,5); // false döndürür
}
Yukarıda equals
adlı bir fonksiyon tanımlı, iki parametre alıyor ve tip ataması u64
olarak yapılmış, geriye mantıksal bir değer döndürdüğünden dönüş tipi
olarak bool
atanmış. Kendisine verilen parametrelerin eşit olup olmama durumuna göre geriye true
ya da false
döndürüyor.
Fonksiyon parametreleri de varsayılan olarak değiştirilemez olduğundan değiştirilebilir kılmak için parametre adından sonra ref mut
eklenmelidir:
fn increment(ref mut num: u32) {
let prev = num;
num = prev + 1u32;
}
Yukarıdaki fonksiyonda num
adlı parametre ref mut
anahtar sözcüğü ile değiştirilebilir olarak atandığından değerini değiştirebildik. Ayrıca ref
anahtar sözcüğü
ile fonksiyon dışında da değeri değiştirilmiş olarak erişebiliriz.
let mut num: u32 = 6;
increment(num);
assert(num == 7); // assert() içerisindeki ifade doğru olduğunda true döndüren bir test aracıdır.
Şu anda ref
ve mut
anahtar sözcüklerinin ayrı ayrı kullanımı mümkün değildir, sadece ref mut
olarak birlikte kullanılabilir.
Struct
Struct birden fazla aynı ya da farklı tipte ve birbiriyle ilişkili değerlerin bir arada olarak tek bir çatı altında tutulduğu veri tipidir. Sway dilinde de tıpkı Rust ve diğer programlama dillerinde olduğu gibi yaygın olarak kullanılırlar.
pub struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
Yukarıdaki kod blokunda bir kullanıcı hesabı hakkındaki verilerin bir arada tutulduğu "User" adlı bir struct tanımlanmış. pub
anahtar sözcüğü ile diğer
programlar tarafından da erişilebilir kılınmış.
Struct içerisindeki veriler aynı yada farklı tipte olabilir, hatta bir verinin tipi başka bir struct da olabilir. Bir struct tanımlandıktan sonra o struct tipinde değerler oluşturmanın birden farklı yolu vardır.
pub struct Point {
x: u64,
y: u64,
}
let mut first = Point {
x: 34,
y: 61,
};
first.x = 56;
Yukarıda "Point" adlı bir struct tanımladık o "first" adlı bir değişkeni o struct tipinde oluşturup içerisindeki verilerin değerlerini atadık. mut
anahtar
sözcüğü ile değiştirilebilir kıldığımız için nokta notasyonuyla "x" değişkenine erişip değerini değiştirebildik.
let x_val = 28;
let y_val = 52;
let mut second = Point {
x: x_val,
y: y_val,
};
let x = 12;
let y = 5;
let mut third = Point { x, y };
Yukarıdaki kod blokunda ikinci bir yol ile struct örneği oluşturulmuş. Değişkenler struct dışında tanımlanarak daha sonra Point struct'ının içerisindeki
değişkenlere atanıyor. Üçüncü yolda ise eğer struct içerisindeki değişkenler ile aynı adda tanımlanan değerler varsa bu değişkenler doğrudan struct içerisine
yazılır, yani { x: x }
şeklinde iki kez yazmaya gerek yoktur.
let point1 = Point {
x: 28,
y: 61,
};
let Point { x, y } = point1;
Yukarıdaki kod blokunda görüldüğü üzere destructuring
yani parçalama yöntemiyle bir struct'ın ögelerini çıkartıp değişkenlere atayabiliriz.
Enum
Bir tipin birden fazla olasılıkta alabileceği değerleri bir arada tutmak için kullanılan yapılara enum
denilir. Örneğin bir cismin alabileceği farklı renkleri
bir enum içerisinde tutabiliriz:
enum Color {
Blue: (),
Red: (),
White: (),
Green: (),
}
fn main() {
let blue = Color::Blue;
let white = Color::White;
}
Yukarıdaki örnekte "Color" adında bir enum tanımladık, içerisinde dört farklı rengi barındırıyor. Daha sonra bu enum içerisindeki her bir değere ::
notasyonuyla
erişerek bir değişkene atayabiliriz.
Enum varyantları (farklı değerleri) bir struct içerisindeki değişkenlere de atanabilir:
enum Color {
Blue: (),
Red: (),
White: (),
Green: (),
}
struct Car {
color: Color,
price: u64,
}
fn main() {
let my_car = Car {
color: Color::White,
price: 3500,
};
}
Yukarıdaki kod blokunda Car adlı bir struct tanımlanmış ve sahip olduğu "color" ögesine tip olarak Color adlı enum atanmış. Daha sonra "my_car" adlı değişkende bu struct örneği oluşturularak "color" verisine değer atamasında Color enum'ının bir varyantı atanmış. Benzer şekilde kullanımı struct içinde enum yerine enum içinde enum kullanılarak da yapılabilir.
Metotlar ve İlişkisel Fonksiyonlar
Metotlar (Method) tıpkı fonksiyonlara benzerler, fn
anahtar sözcüğü ile oluşturulurlar ve parametre alıp geriye bir değer döndürebilirler. Fonksiyonlardan farkı
bir struct ya da enum'a bağımlı bir şekilde oluşturulmalarıdır. Oluşturuldukları struct'a bağlı olduklarından bir metodun ilk parametresi her zaman self
' tir ve
o struct'a referansı temsil eder, yani self
ile o struct'a erişilebilir ve böylece struct içerisindeki değişkenler üzerinde çeşitli işlemler yapılabilir.
İlişkisel Fonksiyonlar da tıpkı metotlar gibidir, bir struct veya enum'a bağlı olarak oluşturulurlar ancak metotlardan farklı olarak ilk parametreleri self
değildir,
böylece struct içerisindeki değişkenlere erişimleri yoktur.
Bir metot ya da İlişkisel fonksiyon oluşturmak için impl
anahtar sözcüğü kullanılır.
script;
struct Foo {
bar: u64,
baz: bool,
}
impl Foo {
fn baz_true(self) -> bool { // metot
self.baz
}
fn new(number: u64, boolean: bool) -> Foo { // İlişkisel fonksiyon
Foo {
bar: number,
baz: boolean,
}
}
}
fn main() {
let foo = Foo::new(42, true);
assert(foo.baz_true());
}
Yukarıdaki script kodlarında ilk önce "Foo" adlı bir struct tanımlanmış. Daha sonra impl Foo
diyerek bir kod bloku açılarak Foo adlı struct'tan bir bir metot ve
bir ilişkisel fonksiyon oluşturulmuş. baz_true
parametre olarak self
aldığından bu bir metottur, artık struct içerisindeki verilere self.bar
ve
self.baz
ile erişebiliriz. Metotları çağırmak için foo.baz_true()
şeklinde nokta notasyonu kullanılır.
new
parametre olarak self
almadığından bu bir İlişkisel fonksiyondur, çoğunlukla new
adı verilerek ilişkili olduğu struct'ın bir örneğini (instance)
oluşturmak istediğimizde bu şekilde yaygın olarak kullanılır, ancak elbette "new" dışında başka bir ad da verilebilir.
Metotlar ve İlişkisel fonksiyonlarda da ref mut
kullanılabilir.
struct Coordinate {
x: u64,
y: u64,
}
impl Coordinate {
fn move_to_right(ref mut self, distance: u64) {
self.x += distance;
}
}
fn main() {
let mut point = Coordinate { x: 2, y: 2 };
point.move_to_right(6);
assert(point.x == 8);
assert(point.y == 2);
}
Yorumlar
Yorum satırları (comments) kod üzerinde küçük bilgi notları bırakmak için yazılan ve derleyicinin görmezden geldiği satırlardır. Sway'de yorum satırları tıpkı
diğer programlama dillerinde olduğu //
kullanılarak yapılır.
fn main() {
let x = 12; // bu bir yorum satırı
/*
Çok satırlı yorum yazmak istersen
buradaki gibi yapabilirsin.
*/
let baz = 8;
}
Yukarıdaki örnekte görüldüğü gibi yorumları birden çok satıra yaymak istersek başlangıç olarak /*
ve bitişte de */
kullanılabilir.
Kontrol Akışı
If
Sway ile koşul yapılarını kurabilmek için diğer programlama dillerindeki gibi if
ve else if
yapıları kullanılabilir:
fn main() {
let number = 8;
if number % 5 == 0 {
// işlemler
} else if number % 4 == 0 {
// başka işlemler
} else {
// daha başka işlemler
}
}
Tıpkı Rust'ta olduğu gibi Sway'de de if
yapıları bir eşitliğin sağ tarafına kullanılarak gelen sonuç eşitliğin sol tarafındaki let
anahtar sözcüğü ile
başlayan bir değişkene eşitlenebilir.
let my_var = if my_bool < 12 { foo() } else { bar() };
Yukarıdaki kod satırında if
yapısından değerlendirilerek gelen sonuç my_var
adlı değişkene eşitlenmiş.
Match
match
yapılarında if
ifadelerinden farklı olarak olası bütün durumlar tek tek ele alınır ve değerlendirilir, olası bütün durumların ele alınmadığı
bir durumda derleyici hata verecektir.
enum Weather {
Sunny: (),
Rainy: (),
Cloudy: (),
Snowy: (),
}
let currentWeather = Weather::Sunny;
let avgTemp = match currentWeather {
Weather::Sunny => 80,
Weather::Rainy => 50,
Weather::Cloudy => 60,
Weather::Snowy => 20,
};
Yukarıdaki kod blokunda hava durumunu temsil eden bir enum tanımlanmış ve halihazırdaki havanın durumuna göre ortalama sıcaklık verisi match
ifadesi
ile değerlendirilmiş. Bu örnekte match
ifadesi içerisinde hava durumunun bütün olası değerleri eşleştirilebilmiş ancak bazı durumlarda olası eşleşmelerin
sayısı çok fazla ya da belirsiz olabilir. Böyle durumlarda bilinen ya da bilinmeyen olası diğer bütün durumların eşleşmesi _
ile sembolize edilir.
let x = 12;
match x {
5 => on_odd(x),
_ => on_even(x),
};
Yukarıdaki örnekte "x" değişkeni için bir match ifadesi oluşturulmuş. Eğer değeri 5 ise yapılacak eşleşme belirtilmiş ancak x'in diğer bütün olası değerleri için
bu durumlar _
(alt tire) ile sembolize edilip eşleşmesi yapılmış.
Döngüler (loop)
Sway'de döngüler yalnızca while
ile sınırlıdır. While döngüleri, verilen bir koşul doğru sürece içerisindeki kod blokunun çalışmaya devam etmesini sağlayan yapılardır.
Bir while döngüsünün kaç defa tekrarlayarak çalıştığını gösteren değere "iterasyon sayısı" denir.
while value < 10 {
value = value + 1;
}
Yukarıda bir while döngüsü oluşturularak value < 10
ifadesi doğru olduğu sürece döngüde kalması ve değerinin bir arttırılması sağlanıyor.
Bir döngüyü sonuna kadar tamamlamadan erken sonlandırmak istendiğinde break
ifadesi kullanılabilir. Aşağıdaki kod blokunda "counter" değeri "num" değerinden
büyük olması durumunda döngüden çıkılması isteniyor, aksi durumlarda ise döngü çalışmaya devam ediyor.
fn break_example() -> u64 {
let mut counter = 1;
let mut sum = 0;
let num = 10;
while true {
if counter > num {
break;
}
sum += counter;
counter += 1;
}
sum // 1 + 2 + .. + 10 = 55
}
Bir döngü devam ederken belli bir kısmını atlayıp bir sonraki iterasyona geçmek istenilen durumlarda ise continue
kullanılır. Aşağıdaki kod blokunda "counter"
değeri "num" değerinden küçük olduğu sürece döngünün devam etmesi isteniyor ve "counter" değeri her iterasyonda bir arttırılıyor. Ancak eğer counter
'ın ikiye
bölümünden kalan 0 ise yani bir çift sayı ise herhangi bir işlem yapılmadan devam edilmesi sağlanarak sadece tek sayılar değerlendirilip toplamı bulunuyor.
fn continue_example() -> u64 {
let mut counter = 0;
let mut sum = 0;
let num = 10;
while counter < num {
counter += 1;
if counter % 2 == 0 {
continue;
}
sum += counter;
}
sum // 1 + 3 + .. + 9 = 25
}
Sway iç içe while
döngülerini de destekler. Böyle yapılarda en dıştaki döngüden çıkılmadığı sürece içerideki döngüler de her iterasyonda çalıştırılmaya devam edecektir.
while durum_1 == true {
// işlemler
while durum_2 == true {
// başka işlemler
}
}