Pull to refresh
30
0
Станислав Ткач @DarkEld3r

Rust developer

Send message
На мой взгляд большинство программистов пришет unwrap потому что понимает — данные в норме, в этом месте, должны быть, а если их нет значит программа в некорректом состоянии, логичто в этом случае бросить панику

Если именно так, то это как раз нормальное применение паники. Если мы не можем (удобно) выразить в типах необходимые ограничения и программа оказалась в разломаном состоянии, то это баг и сделать с этим мало что можно. В идеале правда использовать не unwrap, аexpect или добавить комментарий объясняющий, что происходит.


вторая причина — если все писать через map и т.п. то код очень сильно увеличивается в размере, пишется намного дольше, становиться сложнее для восприяти и рефакторинга.

А вот тут уже что-то не так. То, что язык заставляет явно проверять данные перед использованием — это его преимущество. Если им не пользоваться, то, возможно, имеет смысл взять что-то другое. Возможен вариант, что данные проверяются не там где надо: нет смысла таскать по всей кодовой базе условный Option чтобы анврапать его в каждой функции, надо сделать правильную обработку в одном месте, а дальше передавать уже гарантированное присутствующее значение.


Впрочем, с исключениями код действительно получается короче, но надо понимать, что это и преимущество и недостаток.

И что компилятор с этим будет делать?

Компилятор сможет производить дополнительные оптимизации полагаясь на то, что эта ветка кода никогда не выполнится.


или при его достижении программа выбросит ошибку, что туда нельзя?

При достижении будет UB.

Так Eclipse — не компилятор.

Это немного спорный вопрос. Предположим, что у нас есть однопоточная программа или алгоритм и стоит задача "эффективно использовать все доступные ядра". Я бы сказал, что в таких условиях это вполне баг.

Вдобавок, вынос этого макроса в либу — это +1 процедурный макрос со всеми вытекающими.

Честно говоря, не понял о каких последствиях речь. Реализация ведь и так есть, просто спрятана внутри компилятора, а не стандартной библиотеки. Если её перенести, то почему станет хуже?

Предположу, что логика такая: если на результате функции висит #[must_use], то она (скорее всего) чистая. Но да, сравнение слегка странное.

Не очень в теме, но в расте стандартную библиотеку и компилятор не одни и те же люди делают?.. Версионируется оно точно вместе. В целом я согласен, что библиотечная реализация лучше, но в данном конкретном случае разница не кажется принципиальной. Плюс есть подозрения, что такая "магическая" реализация — это последствия поздней стабилизации макросов, когда раст 1.0 уже был, а свой format! написать ещё было нельзя.

Дык, (быть готовым) читать в итоге придётся всё равно все возможные варианты.

Если серьёзно, то когда хочется функциональщины, то выбор между двумя "семействами" (Lisp или потомки ML) — вполне естественный.

Ну ладно, не буду спорить. Похоже я не могу представить как это когда "просто хочется функциональщины". (:


Просто мне кажется, что множества любителей динамической и статической типизации не очень сильно пересекаются. Опять же, в моём понимании, лисп (тем более Common Lisp, о котором шла речь) — это, в первую очередь, макросы и "гибкость".

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

Не минусовал, но попробую предположить откуда такая реакция. На мой взгляд языки чуть ли не максимально разные, даром что оба принято называть функциональными. То есть, вопрос звучит примерно как "питон или С?" — в большинстве случаев такой выбор просто не стоит, он определяется предметной областью и личными предпочтениями. Опять же, мы ведём это обсуждение в блоге компании, которая топит за статическую типизацию.


P.S. Обычно такое негодование ещё минусов собирает. (:

У меня есть вопрос, а зачем использовать Rust в таком небольшом проекте?

А почему размер проекта имеет значение? Если бы код писался на С++, а не на расте вопрос всё равно возник бы? Ну или можно вывернуть другую сторону: "зачем использовать С в таком небольшом проекте, разве асма недостаточно?"


Признаюсь честно, я предвзят, но спрашиваю тоже без критики и агрессии. (:

unwrap on None в неосновном потоке не приводит к завершению программы.

Так-то и в основном потоке панику можно перехватить.


Паника безопасна.

Да, но с оговорками. Если нет ансейфа, то UB действительно не случится, но и тогда программа может оказаться в разломанном состоянии. Если код написан грамотно, то такого не случится, но в нормальном коде и анврапов особо не будет.

Просто во всяких Хаскелях культура такая, что там обязательно обзовут аналог unwrap именем "unsafeUnwrap". Кмк.

Тут два момента. Во первых, соглашения — если привыкнуть, то за unwrap/expect глаз цепляется не хуже, чем за unsafe префикс. В этом плане хуже, что паниковать могут другие методы, например, доступ по индексу через квадратные скобки. Это тоже можно порешать, но уже костылём (линтом Clippy). Во вторых, ансейф в расте обозначает конкретное подмножество проблем, а не просто "потенциально опасная операция". Паниковать или допускать утечки — "безопасно".

Почему бы не поддержать в компиляторах extern "Rust"

А как это должно выглядеть?


Во первых, не представляю вызов дженериков из другого языка (аналогично с плюсовыми шаблонами). Сюда же хитрости с бороу чекером — это получается компилятор условной джавы должен будет проверять, что растовые функции правильно вызываются? Если всё это вырезать, то останется примерно тот же extern "C", что и в расте сделать можно.


Во вторых, у раста нет стабильного ABI.

А async-std вроде как теперь стандарт

Почему? Только из-за наличия "std" в названии? Может, конечно, я варюсь в пузыре и сильно заблуждаюсь, но больше похоже на то, что эта библиотека умерла. Из того о чём знаю: растовая libp2p изначально использовала как async-std, но и там сделали поддержку токио. О случаях когда токио не поддерживается не слышал.


Ну и я привёл ссылки не количество коммитов, то есть "активность разработки", а не число скачиваний. Хотя и по этому параметру у async-std всё не очень (1,321,707 недавних скачиваний против 7,417,479 у токио).


Ну в той же мере, что и slog_scope.

Всё-таки чуть-чуть эргономичнее из-за атрибутов и прочих мелких удобств. (:

С другой стороны, возможно язык не поддерживает простоту написания длинных монадических цепочек с Result? Ну как в Хаскеле это просто блок do.

Не думаю, что дело в этом. В расте принято обмазываться вопросиками и код в таком стиле писать не сложно, но это не всегда спасает. Вот предположим, что у нас есть вектор в котором гарантированно не меньше пяти элементов. Можно везде писать get(2).and_then(…), но не хочется. Особенно если функция без этого могла бы возвращать просто значение, а не Result/Option. Ответственный человек завернёт такой код в абстракцию и напишет комментарий (и тест заодно). Принципиально эту проблему решают разве что зависимые типы, ну или я чего-то не знаю про хаскель.

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

Мне кажется, что токио всё-таки победил, но сильно спорить не буду. Хотя графики активности говорят сами за себя:
https://github.com/tokio-rs/tokio/graphs/contributors
https://github.com/async-rs/async-std/graphs/contributors


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


После .NET грустно смотреть на отсутствие какого-нибудь LogContext который бы позволял в определенном скоупе добавлять в лог данные.

Кажется, что tracing решает эту задачу.

Я знаю, кто — кто-то, кто вставил unwrap() в темные глубины 100500-того крейта, который используется в таком сервисе. /s

Ну если так говорить, то в чём разница с вызовом std::abort внутри сторонней библиотеки?.. По большому счёту, "внезапный unwrap" — это баг. Да, язык от всех проблем не защищает, увы.

А так, вы правы, в го с ними то же, что и в си.

Разве?.. Вижу вот такое:


For signed integers, the operations +, -, *, /, and << may legally overflow and the resulting value exists and is deterministically defined by the signed integer representation, the operation, and its operands. Overflow does not cause a run-time panic. A compiler may not optimize code under the assumption that overflow does not occur. For instance, it may not assume that x < x + 1 is always true.

А в С ряд операций (включая сдвиг влево) с знаковыми целыми может приводить к UB.

Information

Rating
5,130-th
Date of birth
Registered
Activity