Обновить
16

Пользователь

1
Подписчики
Отправить сообщение

А. Вы уверены что средний человек способен конструктивно проводить переизбыток свободного времени? Потому что если нет, то он просто будет сидеть на антидепрессантах или каком-нибудь другом наркотике, весь день смотреть ТВ/ютуб и в целом быть несчастным.

Б. Для человека, как для любого другого животного, труд это нормально. Мы эволюцировали для того чтобы преодолевать трудности по жизни. Если у человека это отнять, то он начнёт потихоньку сходить с ума (возвращаемся к пункту А).

В. Аристократы не просто отдыхали пожизненно, они вообще-то служили монарху, в том числе они были обязаны служить в армии или на чиновьичей должности. Так что у них были и обязанности, не только привилегии.

Г. Почему вы считаете весь ручной труд чем-то унизительным? Не поверите, есть куча слесарей, электриков и так далее, которые гордятся своей работой, которым приятно делать что-то руками (вместо того чтобы просиживать штаны в офисе).
Да, давайте отберём у дяди Васи смысл его жизни и скажем "вот, теперь вы свободный человек!".

И правда. Пожалуй это недостаток, что более опасный способ сделан как более лёгкий для использования (x as u64 проще написать чем u64::try_from(x))

В голанге достаточно своих способов стрелять в ноги, не говоря об очень ограниченной выразительности языка.

Если говорить о примере из статьи:

  • С int и float там всё в порядке, типизация строгая;

  • С Quantity и Price в принципе нормально. Разве что там где раст потребует явно указывать тип даже у статических значений (например, можно указать только Quantity(100)), го допускает простое 100 (скорее минус по читаемости, чем по наличию багов).

  • На счёт парсинга строки. Проверка ошибок в го не обязательна, т.к. результат и ошибка возвращаются как два отдельных значения (а не одним значением как в раст). Программист вполне может проигнорировать (или забыть) проверку err значения и использований невалидный результат. К счастью ошибочный результат парсинга будет ноль, но в общем случае никто не гарантирует что там безопасное значение.
    Конечно есть библиотеки для го, которые добавляют генерик Either тип, но из-за того что в го нет нормальных енамов и генериков, использовать Either тип это тот ещё геморрой.

  • Отдельное веселье это парсинг строк в го, потому что динозавровая стандартная библиотека ещё до генериков не доросла. Там ParseUint всегда возвращает uint64. Если вам нужен какой-нибудь uint16, то придётся делать конвертацию uint64 -> uint16, за что на вас уже накричат линтеры (в общем случае то преобразование небезопасное)...

А как вы в Rust сделаете это некорректное преобразование в u64?

Если на String вызвать Into<String>, то по-сути никакой работы сделано не будет: внутри вызовется From<String> на String, который вернёт эту же самую строку, ничего с ней не сделав.
Если на String вызвать ToString, то там внутри будет клонирование, т.е. будет выделение памяти на куче (потому что ToString принимает &self, в отличии от Into<String>).
А вот вызовы ToString и Into<String> на &str будут идентичными.
То есть Into<String> позволит передавать владение String, там где есть такая возможность.

P.S. Если вы ожидаете, что в функцию можно передавать только &str или String, то лучше вместо ToString использовать Into<String>.
Во-первых, Into<String> будет эффективнее.
Во-вторых, с ToString можно напороться на то что в функцию можно передать тот же i32.

Что-то мне хочется не согласиться. В каких случаях это причинит боль? Мне кажется любая функция, которой не нужно владеть строкой, вполне может принимать &str.

ToString это хороший подход, но он применим в основном в апи, чтобы уюзеру было удобно, а внутри кода крейта обычно что-то одно передаёшь, или &str, или String.

Универсальный переносимый сервер на двух потоках можно и на Rust написать.
Это мне кажется больше обучающая статья про async, поэтому некоторые примеры могут быть ходульные (что в целом распространённая проблема обучающих статей). Главное что показывает как async работает.

А в чём собственно проблема писать "э" там где на слух "э"? Особенно учитывая что это слова, которые в языке недавно и с их написанием можно экспериментировать.

Если говорить о расте, часть ооп характеристик у него есть - инкапсуляция и полиморфизм. Только наследования нет, что на самом деле в крупном софте может быть плюсом (отсутствие наследования делает код проще для понимания имхо).

А так, даже без вообще каких-либо фишек ооп крупный софт пишут - ядро Линукс например

ты приплел политику и военных

Из статьи:

с помощью специалистов МАИ смогли собрать и запустить модель самолета, модель авиабомбы

Ну извините. В вашем мире походу вообще должна быть только одна операционка, одна архитектура с одним набором инструкци...

Это вы о чём?

Так же в вашем идеальном мире...

Откуда вы про идеальный мир взяли? Пакетные менеджеры и средства сборки это что-то что есть в применяющихся на практике ЯП.

Я не говорю, что это хорошо, что в плюсах это не совсем тривиально

Вы по крайней мере не считаете это проблемой, а если кто-то считает, то "пусть идёт программировать на языках для ненастоящих программистов".
(Я ни в коем случае не адвокат js и питона, просто вы тут ложную дихотомию устроили).

Но это достаточно гибко и всё зависит от потребностей

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

Потому что программист должен изучать арбитрарный набор всякого (часто) плохо документированного инструментария с кривым интерфейсом и недостатком примеров, чтобы сделать совершенно типовую рутинную задачу (собрать проект или добавить в него зависимость).
Потом он прийдёт в другой проект, а там свои погремушки, поэтому надо учить новый набор опенсорсных вкусностей.
(Не важно что все эти QOL вещи есть в любом современном языке, не зависимо от его низко/высоко-уровневости, если ты не страдаешь по пустякам, то ты не Труъ программист)

Говнокод само собой можно везде написать, но всегда нужно ещё учитывать человеческий фактор. Некоторые ошибки проще совершить в одном языке и сложнее в другом. Просто программисты на c++ любят писать что ошибки с памятью делают только нубы, а "тру" программисты ошибок не делают и память освобождают. Но ведь это сложно всё время быть начеку, особенно в больших проектах, хоть раз да потеряешь бдительность ошибёшься. И раст пытается устранить некоторые ошибки, которые возникают из-за человеческого фактора, уменьшает ментальную нагрузку на программиста, там где это можно сделать.
(Не являюсь пропагандистом раста в плане "нужно всё на нём переписать", хоть и люблю его, но всё таки некоторые преимущества по сравнению с плюсами у него есть)

Передача владения это концепция на уровне языка. Под капотом в некоторых случаях будет производится копирование.

Вопрос, что вы пытаетесь сказать? Что этот паттерн неприменим в случаях когда скопировать 32 байта это дорого? Наверное, но это достаточно редкий случай, мне кажется в подавляющем большинстве производительность при наивной реализации будет более чем достаточной, в остальных случаях уже надо смотреть на конкретную задачу и сиходя из неё придумывать оптимизацию.

Option держит ссылку если ему явно сказать: Option<&int> или если храните более долговременные данные, то с умным указателем Option<Rc<int>>.
ИМХО в случае с User<Editor> это скорее всего не затратно, потому что компилятор догадается, что сама структура не меняется (меняется PhantomData только, которая в памяти не хранится, а есть только на этам компиляции) и не будет копировать.

В целом я согласен, но это уже детали реализации, суть паттерна это не меняет.

P.S. Такой перенос данных от старого билдера к новому (копирование) это в худшем случае мемкопи, в лучшем компилятор поймёт что мы делаем и не будет билдер менять никак. То есть никакого дополнительного выделения динамической памяти производится не будет, если у нас внутри билдера есть поля с динамической памятью.

Да, там данные полностью перемещаются из билдера в билдер. Что-то вроде:

fn with_bin_data(self, data: &[u8]) -> MyStructBuilder<ReadyToBuild>
{
  ...устанавливаем data...
  return MyStructBuilder {
    data: self.data,
    pd: PhantomData
  };
}

Есть ли в этом проблема?

PhantomData нужна по единственной причине: rust запрещает добавлять в структуру генерик параметр и при этом не использовать его внутри самой структуры. Поэтому в неё добавляется поле PhantomData<State>. Больше PhantomData ничего не делает.

Информация

В рейтинге
5 322-й
Зарегистрирован
Активность

Специализация

Бэкенд разработчик
Средний
Rust