Как стать автором
Обновить
71.33

Rust *

Мультипарадигмальный компилируемый язык

Сначала показывать
Порог рейтинга

Полезный антипаттерн в Rust

В Rust нередко используются типы обертки (newtype), которые помогают строже контролировать обрабатываемые данные.

Представим функцию, которая работает со списоком пользователей, но только если они являются администраторами, то вместо просто передачи массива идентификаторов можно использовать тип обертку, чтобы быть уверенным в корректности данных:

struct Admins(Vec<u128>);

Теперь можно использовать этот тип:

fn print_admin_count(users: Admins) {
    println!("admins count: {}", users.0.len());
}

Это работает, но выглядит уже не так приятно, как если бы мы просто использовали массив users.len().

В Rust существуют типажи (traits) Deref/DerefMut, которые решают эту проблему, если мы реализуем их для типа обертки, то это позволит работать с внутренним типом напрямую:

impl Deref for Admins{
    //...
}

fn print_admin_count(users: Admins) {
    println!("admins count: {}", users.len());
}

Полный сниппет

Документация предупреждает, что эти типажи должны использоваться только для умных указателей, хотя практика более свободного использования расходится все шире.

Всего голосов 1: ↑1 и ↓0+1
Комментарии0

в Rust есть метод transpose, иногда бывает полезен, особенно хорошо работает с anyhow:

use std::str::FromStr;
use anyhow::Context;

fn add(a: Option<&str>, b: Option<&str>) -> anyhow::Result<f32> {
    let a = a.map(f32::from_str).transpose()?.context("not a value")?;
    let b = b.map(f32::from_str).transpose()?.context("not a value")?;
    Ok(a + b)
}

fn main() {
    println!("{:?}", add(Some("12"), Some("1.2")));
    println!("{:?}", add(Some("a"), Some("1.2")));
    println!("{:?}", add(None, Some("1.2")));
}

вывод:

Ok(13.2)
Err(invalid float literal)
Err(not a value)
Всего голосов 2: ↑2 и ↓0+2
Комментарии0
2