Zig'de Error Union Operatorü
Error Union Operator in Zig
Error Union kavramı zig programlama dilinde ya hata ya da belirtilen veri türünde veri döndüren yapılar oluşturmak için kullanılır.
/// A common case for errors is a situation where we're expecting to
// have a value OR something has gone wrong. Take this example:
//
// var text: Text = getText("foo.txt");
//
// What happens if getText() can't find "foo.txt"? How do we express
// this in Zig?
//
// Zig lets us make what's called an "error union" which is a value
// which could either be a regular value OR an error from a set:
//
// var text: MyErrorSet!Text = getText("foo.txt");
//
// For now, let's just see if we can try making an error union!
//
const std = @import("std");
const MyNumberError = error{TooSmall};
pub fn main() void {
var my_number: MyNumberError!u8 = 5;
// Looks like my_number will need to either store a number OR
// an error. Can you set the type correctly above?
my_number = MyNumberError.TooSmall;
std.debug.print("I compiled!\n", .{});
}
Buradaki kodda ilk olarak farkedeceğimiz şey error union operatörü olarak bilinen !
operatörü ile yazılmış olan aşağıdaki kod yapısıdır:
var my_number: MyNumberError!u8 = 5;
Bu kod blogu ya u8
formatında bir değer döndürür ya da daha önceden tanımlamış olduğumuz MyNumberError
yapısına ait bir hata (error) döndürür.
const MyNumberError = error{TooSmall};
Yukarıda MyNumberError
isimli bir error set tanımladık. Bu array içerisinde TooSmall
gibi bir değer alabileceğini belirttik.
Daha sonrasında ise bu değeri doğrudan değişkene atadık.
my_number = MyNumberError.TooSmall;
Programımız hatasız bir şekilde çalıştı. Çünkü sadece tanımlamalar yaptık ve bu aşamaya dek hata döndürebilecek hiçbir şey bildirmedik.
Error Union as Return in Zig
Bu kısımda bir fonksiyonun döndürdüğü değer olarak error union yapılarını değerlendireceğiz. Bu fonksiyonların döndürdüğü değerlerde hata kontrolü yaparken kullanacağımız yapılardır.
//
// One way to deal with error unions is to "catch" any error and
// replace it with a default value.
//
// foo = canFail() catch 6;
//
// If canFail() fails, foo will equal 6.
//
const std = @import("std");
const MyNumberError = error{TooSmall};
pub fn main() void {
const a: u32 = addTwenty(44) catch 22;
const b: u32 = addTwenty(4) catch 22;
std.debug.print("a={}, b={}\n", .{ a, b });
}
// Please provide the return type from this function.
// Hint: it'll be an error union.
fn addTwenty(n: u32) MyNumberError!u8 {
if (n < 5) {
return MyNumberError.TooSmall;
} else {
return n + 20;
}
}
Şimdi kodu aşağıdaki şekilde parçalarına ayıralım.
const std = @import("std");
Zig’in standart kütüphanesini (std
) içe aktarır. Böylece std.debug.print
gibi fonksiyonları kullanabiliriz.
const MyNumberError = error{TooSmall};
Bu satır, MyNumberError
isminde bir hata türü tanımlar. İçerisinde sadece bir hata durumu vardır: TooSmall
. Bu bir error set’tir.
pub fn main() void {
const a: u32 = addTwenty(44) catch 22;
const b: u32 = addTwenty(4) catch 22;
std.debug.print("a={}, b={}\n", .{ a, b });
}
Ana işlemlerimizin yapıldığı fonksiyonumuz ise yukarıdaki şekildedir. Burada da özel bir yazım görüyoruz:
const a: u32 = addTwenty(44) catch 22;
const b: u32 = addTwenty(4) catch 22;
4
değeriaddTwenty
fonksiyonuna gönderilir.4 < 5
olduğu için bu çağrı hata döner:MyNumberError.TooSmall
- Bu durumda
catch
devreye girer ve22
değeri atanır.catch
yapısı istenen değer sağlanmazsadefault
(varsayılan) değer döndürmek için kullanılan bir yapıdır.catch
değeri iki değer arasında mukayese yaparak hata ya da değer döndürülmesini sağlar.
Son olarak da sonuçları ekrana yazdırıyoruz:
std.debug.print("a={}, b={}\n", .{ a, b });
- Değişkenleri ekrana yazdırır.
a = 64
olur çünkü44 + 20 = 64
b = 22
olur çünkü hata oluştu vecatch 22
çalıştı.
İşlem sırasında diğer kontrol mekanizması olan addTwenty
isimli fonksiyonu açıklayalım:
fn addTwenty(n: u32) MyNumberError!u8 {
if (n < 5) {
return MyNumberError.TooSmall;
} else {
return n + 20;
}
}
addTwenty
fonksiyonumuz u32
türünde n isimli bir değer alır. Bu değeri işlemlere tabi tutar ve bunun sonucunda MyNumberError
hata setindeki değerlerden birini ya da u8
veri türünde bir değer döndürür.
- eğer n sayımız 5'ten küçük ise
MyNumberError
hata setindenTooSmall
isimli hatamızı döndürür. - eğer n sayısı 5'e eşit veya büyükse n sayısına 20 ekleyerek stdout olarak döndürür.