• Как оптимизировать код в rust при помощи trait?

    Trame2771
    @Trame2771
    Как я понял, дать гарантии компилятору, для того, чтобы сделать то, что вы хотите, пока нельзя, или сделать это будет очень неочевидно. Гарантии нужны потому что язык безопасный. Возможно когда добавят кастомные маркеры в язык, тогда можно будет чё-то гарантировать. А пока можно пользоваться макросами. Это не так плохо как кажеться. Это не нагружает бинарник, нагружает только компилятор. Причем линейно. Нагрузка на компилятор будет составлять (Количество типов * количество функций). Правда если будет использоваться больше одного типа в структуре, тогда будет применятся комбинаторика для определения нагрузки на компилятор. То есть само приложение будет таким же производительным, правда из-за нагрузки на компилятор, он может перестать немного оптимизировать код. Вот решение чтобы не дублировать код:
    mod float_trait {
        pub trait Float {}
        impl Float for f32 {}
        impl Float for f64 {}
    }
    
    use crate::float_trait::Float;
    
    mod float_struct {
        use crate::float_trait::Float;
    
        #[derive(Debug)]
        pub struct FloatStruct<T: Float>
        {
            _a: i8,
            _b: String,
            pub c: T,
        }
        
        macro_rules! impl_float_struct {
            ($($type:ty),*) => {
                $(
                    impl FloatStruct<$type> {
                        pub fn new() -> Self {
                            Self {
                                _a: 2,
                                _b: String::from("hi"),
                                c: 0.3,
                            }
                        }
                    }
                )*
            }
        }
        
        impl_float_struct![f32, f64];
    }
    
    fn main() {
        let fs = float_struct::FloatStruct::<f32>::new();
        println!("{:#?}", fs.c)
    }


    Другое решение, очевидно нагружающее само приложение, и лёгкое для компилятора
    mod float_trait {
        pub trait Float {}
        impl Float for f32 {}
        impl Float for f64 {}
    }
    
    mod float_struct {
        use crate::float_trait::Float;
    
        #[derive(Debug)]
        pub struct FloatStruct<T: std::str::FromStr + Float>
        {
            _a: i8,
            _b: String,
            pub c: T,
        }
    
        impl<T: std::str::FromStr + Float> FloatStruct<T> {
            pub fn new() -> Self {
                Self {
                    _a: 2,
                    _b: String::from("hi"),
                    c: {
                        let Ok(r) = "0.3".parse::<T>()
                            else {unreachable!()};
                        r
                    }
                }
            }
        }
    }
    
    fn main() {
        let fs = float_struct::FloatStruct::<f32>::new();
        println!("{:#?}", fs.c)
    }
    Ответ написан
    1 комментарий
  • Как оптимизировать код в rust при помощи trait?

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

    Подозреваю, что тебе хочется что-то вроде "сложить два числа, но чтобы можно было и f32 туда и f64". Для этого есть множество стандартных трейтов: Add, Sub, Div, Mul, *Assign, которые и стоит использовать. Например:

    fn f<T: Add<Output = T>>(x1: T, x2: T) -> T {
        x1 + x2
    }
    
    fn main() {
        println!("{}", f(3.14_f32, 2.7)); // можно f32 + f32
        println!("{}", f(3.14_f64, 2.7)); // а можно f64 + f64
    }
    Ответ написан
    Комментировать
  • Как оптимизировать код в rust при помощи trait?

    vabka
    @vabka
    Токсичный шарпист
    1. Действительно непонятно, для чего и как ты хочешь эти трейты использовать.
    2. Кажется, ты пытаешься переизобрести num
    3. Ошибка у тебя из-за того что ожидается какой-то неизвестный T, а ты пихаешь туда f64
    Тоесть, например, я бы мог захотеть сделать FloatStruct::<f32>::new() но вместо FloatStruct<f32> ты пытаешься вернуть мне FloatStruct<f64>
    Ответ написан
    8 комментариев
  • Как обновить свой Fork репозитарий до последней редакции основного репазитария используя GitHub for Windows?

    CAXAline
    @CAXAline
    Перейти на вкладку Pull Requests
    Создаем новый реквест New pull request
    Пишет, что нечего сравнивать, но не расстраиваемся и жмем switching the base
    Появились отличия родительского и форкнутого проектов. Жмем Create pull request и даем ему название
    Автоматически оказываемся в этом пул реквесте и жмем Merge pull request
    И напоследок Confirm merge
    PROFIT
    Ответ написан
    2 комментария
  • Как правильно делать тесты?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    Избегайте Карго культа.
    Тесты должны быть
    * Достаточными и разумными
    * Каждая ошибка в гите должна быть покрыта тестом и закрыта

    Этого достаточно, движения по покрытию тестами на 100% смешны
    Ответ написан
    2 комментария
  • Почему в результате выводятся различные адреса?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Это происходит потому, что вы храните значения, а не указатели и, соответственно, вот тут for i, a := range t.array в `a` - создаётся копия value.
    Чтобы адреса были одинаковые нужно хранить указатели, а не значения, т.е. нужно делать вот так
    type Test struct {
    	array []*Array
    }

    Поправил ваш код в песочнице, теперь адреса одинаковые
    Ответ написан
    4 комментария
  • Структура проекта на Golang?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Добрый день.

    Это попытка стандартизировать структуру проекта (многие ориентируются на неё)
    https://github.com/golang-standards/project-layout

    Go-Kit - очень грамотная структура, очень
    https://github.com/go-kit/kit

    И обязательно стоит посмотреть
    https://12factor.net/ru/

    Что касается "Т.е. в одном файле может быть сразу модель, сервис и репозиторий. Есть ли какие-то бестпркатики по этому вопросу?" - то это не совсем так, в одном пакете (папке) может быть и модель, и сервис, и репозиторий". Например вот так:
    yourpackage/service.go
    yourpackage/repo.go
    yourpackage/model.go
    И это всё будет доступно в рамках пакета.

    Лично я использую такую схему:
    cmd/ - команды исполняемого файла
    conf/ - конфиги приложения (env файлы)
    init/ - конфиги logrotated, nginx, systemd и т.д.
    pkg/ - публичные пакеты
    pkg/packagename/ - тут определяются интерфейсы (сервиса, репозитория и т.д.) в разных файлах
    pkg/packagename/endpoints/http - endpoint'ы для HTTP
    pkg/packagename/repo/mysql - реализация репозитория на MySQL
    pkg/packagename/repo/gorm - реализация репозитория на GORM (для примера)
    pkg/packagename/service/ реализация сервиса

    Я написал очень кратко, если что-то не понятно или есть вопросы - пишите, я опишу подробнее
    Ответ написан
    3 комментария