Что такое ржавчина
Rust — это компилируемый язык (подобно C и C++) с акцентом на параллельность и безопасность памяти, что чрезвычайно полезно в системах, где важна производительность. Но, будучи современным языком, он имеет некоторые возможности, которые делают его замечательным, как его компилятор, который всегда помогал мне, вот пример, который я видел, как он помогал мне, как будто это был результат модульного теста
пример ошибки компилятора, чтобы показать, насколько он элегантен и чрезвычайно полезен
Тесты ?
В rust по умолчанию есть тесты и работа, которая является менеджером языковых зависимостей. Сегодня я подробнее расскажу о тестах и о том, как легко их создавать и понимать. С хорошей документацией ржавчина не оставляет желать лучшего в этом пункте.
Пример кода теста, обратите внимание, что в нем есть код #[test], который показывает, какая функция может быть использована для тестирования. Она ожидает возврата true или false и на основании этого проходит. assert_eq! может принимать строку в качестве параметров, где вы можете лучше объяснить тест.
#[test]
fn abstract_factory_create_car() {
let car: Box<dyn Vehicle> = factory_method::ShapeFactory::new_vehicle(&VehicleTypes::Car);
let result: &str = car.translocate();
assert_eq!(result, "Moved in land", "Creating a car with a type only ");
}
#[test]
fn abstract_factory_create_boat() {
let boat: Box<dyn Vehicle> = factory_method::ShapeFactory::new_vehicle(&VehicleTypes::Boat);
let result: &str = boat.translocate();
assert_eq!(result, "Moved in water", "Creating a boat with a type only ");
}
#[test]
fn abstract_factory_create_plane() {
let plane: Box<dyn Vehicle> = factory_method::ShapeFactory::new_vehicle(&VehicleTypes::Plane);
let result: &str = plane.translocate();
assert_eq!(result, "Moved in air", "Creating a plane with a type only ");
}
Есть ли у вас типы?
У нас есть типы и указатели, что делает его чрезвычайно выразительным, я могу создавать свои собственные типы, как в Vehicle, но я также могу использовать типы языка, как в result, где я использую ссылку str, которая является фрагментом String, как в случае » moved in something».
Ссылка ?
Будучи языком низкого уровня, мы обладаем некоторыми возможностями и особенностью языка, что замечательно. Концепция ссылок и заимствований, эта концепция чрезвычайно интересна и элегантна для понимания. Если вы передали переменную в качестве аргумента в функцию, вы потеряли право собственности на переменную, компилятор произнесет следующее предложение, когда вы попытаетесь использовать ее снова:
Значение уже было перемещено сюда, если вы хотите передать его снова, вы можете передать его ссылку и изменить типы так, чтобы это поддерживалось
Как работать с займами?
В rust вы можете передавать в функцию вместо переменной и перемещать ее, как требует компилятор, вы можете передавать ее ссылку и работать с ней, но никогда не мутируя и не изменяя значение. Да, существует изменяемость, но вам нужно сказать, что что-то является изменяемым, используя ключевое слово mut
.
Узоры?
Rust — это функционально вдохновленный язык, в нем есть неизменяемость, соответствие шаблонам и другие черты функционального языка. Тем не менее, в нем есть современные возможности объектно-ориентированного программирования, такие как traits и strucs, и очень читабельный код, когда процедурный
#[derive(Debug)]
pub struct Unique {
pub global_const: String,
}
/// Get the singleton that is only once initialized
pub fn get_singleton() -> &'static Mutex<Unique> {
static mut UNIQ: MaybeUninit<Mutex<Unique>> = MaybeUninit::uninit();
static ONCE: Once = Once::new();
ONCE.call_once(|| unsafe {
UNIQ.as_mut_ptr().write(Mutex::new(Unique {
global_const: "Global string".to_string(),
}));
});
unsafe { &*UNIQ.as_ptr() }
}
pub fn set_singleton(value: &str, singleton_instance: &Mutex<Unique>) {
let mut new_value = singleton_instance.lock().unwrap();
new_value.global_const = value.to_string();
}
o Шаблон синглтон
use crate::creational::factory_method::VehicleTypes::{Car as CarType, Plane as PlaneType, Boat as BoatType};
pub trait Vehicle {
fn translocate(&self) -> &str;
}
pub enum VehicleTypes {
Car,
Boat,
Plane,
}
struct Car {}
impl Vehicle for Car {
fn translocate(&self) -> &str {
println!("Moved in land");
"Moved in land"
}
}
struct Boat {}
impl Vehicle for Boat {
fn translocate(&self) -> &str {
println!("Moved in water");
"Moved in water"
}
}
struct Plane {}
impl Vehicle for Plane {
fn translocate(&self) -> &str {
println!("Moved in air");
"Moved in air"
}
}
pub struct ShapeFactory;
impl ShapeFactory {
pub fn new_vehicle(v: &VehicleTypes) -> Box<dyn Vehicle> {
match v {
VehicleTypes::Car => Box::new(Car {}),
VehicleTypes::Boat => Box::new(Boat {}),
VehicleTypes::Plane => Box::new(Plane {}),
}
}
}
Фабричный образец
Еще примеры?
Наконец, я хотел бы оставить пример кода, который я видел на leet code, где он может быть полезен, чтобы показать некоторые приятные детали lang, который даже на низком уровне работает с легкостью, как это делают языки типа java
/// given a list of lists which of the list is the biggest sum
/// as the result of the table!
///
/// _Table_
///
///
/// | Values | Sum | Result| Winner|
/// |--------|-----------|-------|--------|
/// | 1 2 3 | 1 + 2 + 3 | 6 | |
/// | 5 5 5 | 5 + 5 + 5 | 15 | X |
/// | 3 1 4 | 3 + 1 + 4 | 8 | |
///
pub fn biggest_sum(res_: Vec<Vec<i32>>) -> i32 {
res_.iter()
.map(|x| x.iter().sum())
.max()
.unwrap()
}
// Teste da função acima
#[test]
pub fn biggest_sum_test() {
let v1 = vec![1, 2 ,3];
let v2 = vec![5, 5 ,5];
let v3 = vec![3, 1 ,4];
let big_vec = vec![v1, v2, v3,];
let result = biggest_sum(big_vec);
assert_eq!(result, 15, "Testing sum, should return always 15");
}
Проблема кода лита
Да, функции, заканчивающиеся на ! (нет, он не говорит вслух), являются макросами, и это деталь для другого дня, но это делает меня очень счастливым. Мы можем создавать собственные макросы, представляющие сложные функции, такие как vec![1,2,3] — то же самое, что Vec::from([1,2,3]), более простой способ инициализации ссылки