Structları Kullanan Örnek Bir Program
Struct'ları kullanmak isteyebileceğimiz durumları anlamak için, bir dikdörtgenin alanını hesaplayan bir program yazalım. Tek değişkenler kullanarak başlayacak ve programı struct'ları kullanacak şekilde yeniden düzenleyene kadar devam edeceğiz.
Let’s make a new project with Scarb called rectangles that will take the width and height of a rectangle specified in pixels and calculate the area of the rectangle. Listing 5-8 shows a short program with one way of doing exactly that in our project’s src/lib.cairo.
Filename: src/lib.cairo
fn main() {
let width = 30;
let height = 10;
let area = area(width, height);
println!("Area is {}", area);
}
fn area(width: u64, height: u64) -> u64 {
width * height
}
Listing 5-8: Calculating the area of a rectangle specified by separate width and height variables.
Now run the program with scarb cairo-run
:
$ scarb cairo-run
Compiling listing_04_06_no_struct v0.1.0 (listings/ch05-using-structs-to-structure-related-data/listing_03_no_struct/Scarb.toml)
Finished `dev` profile target(s) in 3 seconds
Running listing_04_06_no_struct
Area is 300
Run completed successfully, returning []
Bu kod, her boyutu area
fonksiyonu ile çağırarak dikdörtgenin alanını bulmayı başarır, ancak bu kodu daha net ve okunabilir hale getirmek için daha fazlasını yapabiliriz.
Bu kodun sorunu, area
fonksiyonunun imzasında açıktır:
fn area(width: u64, height: u64) -> u64 {
The area
function is supposed to calculate the area of one rectangle, but the function we wrote has two parameters, and it’s not clear anywhere in our program that the parameters are related. It would be more readable and more manageable to group width and height together. We’ve already discussed one way we might do that in the Tuple Section of Chapter 2.
Tuple'larla Yeniden Düzenleme
Listing 5-9 shows another version of our program that uses tuples.
Filename: src/lib.cairo
fn main() {
let rectangle = (30, 10);
let area = area(rectangle);
println!("Area is {}", area);
}
fn area(dimension: (u64, u64)) -> u64 {
let (x, y) = dimension;
x * y
}
Listing 5-9: Specifying the width and height of the rectangle with a tuple.
Bir yönden, bu program daha iyi. Tuple'lar biraz yapı eklememize izin verir ve artık sadece bir argüman geçiriyoruz. Ancak başka bir yönden, bu versiyon daha az açık: tuple'lar elemanlarını adlandırmaz, bu yüzden tuple'ın parçalarına indeksle erişmemiz gerekiyor, bu da hesaplamamızı daha az açık hale getiriyor.
Genişliği ve yüksekliği karıştırmak alan hesaplaması için önemli olmaz, ancak farkı hesaplamak isteseydik önemli olurdu! width
'ın tuple indeksi 0
ve height
'ın tuple indeksi 1
olduğunu aklımızda tutmamız gerekirdi. Kodumuzu kullanacak başka biri için bu, anlaması ve aklında tutması daha zor olurdu. Verilerimizin anlamını kodumuzda iletemediğimiz için, hataları daha kolaylıkla tanıtmak şimdi daha kolay.
Struct'larla Yeniden Düzenleme: Daha Fazla Anlam Katma
Verilere anlam katmak için struct'ları kullanıyoruz. Kullandığımız tuple'ı hem bütün hem de parçalar için adlarla bir struct'a dönüştürebiliriz.
Filename: src/lib.cairo
struct Rectangle {
width: u64,
height: u64,
}
fn main() {
let rectangle = Rectangle { width: 30, height: 10 };
let area = area(rectangle);
println!("Area is {}", area);
}
fn area(rectangle: Rectangle) -> u64 {
rectangle.width * rectangle.height
}
Listing 5-10: Defining a Rectangle
struct.
Burada bir struct tanımladık ve ona Rectangle
adını verdik. Süslü parantezlerin içinde, width
ve height
olarak tanımlanan alanları, her ikisi de u64
tipinde. Sonra, main
'de width
'ı 30
ve height
'ı 10
olan Rectangle
'ın belirli bir örneğini oluşturduk. area
fonksiyonumuz artık bir parametre ile tanımlanıyor, bu parametreyi rectangle
olarak adlandırdık ve tipi Rectangle
struct'ı. Sonra örneğin alanlarına nokta notasyonu ile erişebiliriz ve 0
ve 1
tuple indeks değerlerini kullanmak yerine değerlere açıklayıcı adlar verir.
Conversions of Custom Types
We've already described how to perform type conversion on in-built types, see Data Types > Type Conversion. In this section, we will see how to define conversions for custom types.
Note: conversion can be defined for compound types, e.g. tuples, too.
Into
Defining a conversion for a custom type using the Into
trait will typically require specification of the type to convert into, as the compiler is unable to determine this most of the time. However this is a small trade-off considering we get the functionality for free.
// Compiler automatically imports the core library, so you can omit this import
use core::traits::Into;
#[derive(Drop, PartialEq)]
struct Rectangle {
width: u64,
height: u64,
}
#[derive(Drop)]
struct Square {
side_length: u64,
}
impl SquareIntoRectangle of Into<Square, Rectangle> {
fn into(self: Square) -> Rectangle {
Rectangle { width: self.side_length, height: self.side_length }
}
}
fn main() {
let square = Square { side_length: 5 };
// Compiler will complain if you remove the type annotation
let result: Rectangle = square.into();
let expected = Rectangle { width: 5, height: 5 };
assert!(
result == expected,
"A square is always convertible to a rectangle with the same width and height!",
);
}
TryInto
Defining a conversion for TryInto
is similar to defining it for Into
.
// Compiler automatically imports the core library, so you can omit this import
use core::traits::TryInto;
#[derive(Drop)]
struct Rectangle {
width: u64,
height: u64,
}
#[derive(Drop, PartialEq)]
struct Square {
side_length: u64,
}
impl RectangleIntoSquare of TryInto<Rectangle, Square> {
fn try_into(self: Rectangle) -> Option<Square> {
if self.height == self.width {
Option::Some(Square { side_length: self.height })
} else {
Option::None
}
}
}
fn main() {
let rectangle = Rectangle { width: 8, height: 8 };
let result: Square = rectangle.try_into().unwrap();
let expected = Square { side_length: 8 };
assert!(
result == expected,
"Rectangle with equal width and height should be convertible to a square.",
);
let rectangle = Rectangle { width: 5, height: 8 };
let result: Option<Square> = rectangle.try_into();
assert!(
result.is_none(),
"Rectangle with different width and height should not be convertible to a square.",
);
}