На мой взгляд большинство программистов пришет unwrap потому что понимает — данные в норме, в этом месте, должны быть, а если их нет значит программа в некорректом состоянии, логичто в этом случае бросить панику
Если именно так, то это как раз нормальное применение паники. Если мы не можем (удобно) выразить в типах необходимые ограничения и программа оказалась в разломаном состоянии, то это баг и сделать с этим мало что можно. В идеале правда использовать не unwrap, аexpect или добавить комментарий объясняющий, что происходит.
вторая причина — если все писать через map и т.п. то код очень сильно увеличивается в размере, пишется намного дольше, становиться сложнее для восприяти и рефакторинга.
А вот тут уже что-то не так. То, что язык заставляет явно проверять данные перед использованием — это его преимущество. Если им не пользоваться, то, возможно, имеет смысл взять что-то другое. Возможен вариант, что данные проверяются не там где надо: нет смысла таскать по всей кодовой базе условный Option чтобы анврапать его в каждой функции, надо сделать правильную обработку в одном месте, а дальше передавать уже гарантированное присутствующее значение.
Впрочем, с исключениями код действительно получается короче, но надо понимать, что это и преимущество и недостаток.
Это немного спорный вопрос. Предположим, что у нас есть однопоточная программа или алгоритм и стоит задача "эффективно использовать все доступные ядра". Я бы сказал, что в таких условиях это вполне баг.
Вдобавок, вынос этого макроса в либу — это +1 процедурный макрос со всеми вытекающими.
Честно говоря, не понял о каких последствиях речь. Реализация ведь и так есть, просто спрятана внутри компилятора, а не стандартной библиотеки. Если её перенести, то почему станет хуже?
Не очень в теме, но в расте стандартную библиотеку и компилятор не одни и те же люди делают?.. Версионируется оно точно вместе. В целом я согласен, что библиотечная реализация лучше, но в данном конкретном случае разница не кажется принципиальной. Плюс есть подозрения, что такая "магическая" реализация — это последствия поздней стабилизации макросов, когда раст 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", что и в расте сделать можно.
Почему? Только из-за наличия "std" в названии? Может, конечно, я варюсь в пузыре и сильно заблуждаюсь, но больше похоже на то, что эта библиотека умерла. Из того о чём знаю: растовая libp2p изначально использовала как async-std, но и там сделали поддержку токио. О случаях когда токио не поддерживается не слышал.
Ну и я привёл ссылки не количество коммитов, то есть "активность разработки", а не число скачиваний. Хотя и по этому параметру у async-std всё не очень (1,321,707 недавних скачиваний против 7,417,479 у токио).
Ну в той же мере, что и slog_scope.
Всё-таки чуть-чуть эргономичнее из-за атрибутов и прочих мелких удобств. (:
С другой стороны, возможно язык не поддерживает простоту написания длинных монадических цепочек с Result? Ну как в Хаскеле это просто блок do.
Не думаю, что дело в этом. В расте принято обмазываться вопросиками и код в таком стиле писать не сложно, но это не всегда спасает. Вот предположим, что у нас есть вектор в котором гарантированно не меньше пяти элементов. Можно везде писать get(2).and_then(…), но не хочется. Особенно если функция без этого могла бы возвращать просто значение, а не Result/Option. Ответственный человек завернёт такой код в абстракцию и напишет комментарий (и тест заодно). Принципиально эту проблему решают разве что зависимые типы, ну или я чего-то не знаю про хаскель.
Я знаю, кто — кто-то, кто вставил 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.
Если именно так, то это как раз нормальное применение паники. Если мы не можем (удобно) выразить в типах необходимые ограничения и программа оказалась в разломаном состоянии, то это баг и сделать с этим мало что можно. В идеале правда использовать не
unwrap
, аexpect
или добавить комментарий объясняющий, что происходит.А вот тут уже что-то не так. То, что язык заставляет явно проверять данные перед использованием — это его преимущество. Если им не пользоваться, то, возможно, имеет смысл взять что-то другое. Возможен вариант, что данные проверяются не там где надо: нет смысла таскать по всей кодовой базе условный
Option
чтобы анврапать его в каждой функции, надо сделать правильную обработку в одном месте, а дальше передавать уже гарантированное присутствующее значение.Впрочем, с исключениями код действительно получается короче, но надо понимать, что это и преимущество и недостаток.
Компилятор сможет производить дополнительные оптимизации полагаясь на то, что эта ветка кода никогда не выполнится.
При достижении будет UB.
Так Eclipse — не компилятор.
Это немного спорный вопрос. Предположим, что у нас есть однопоточная программа или алгоритм и стоит задача "эффективно использовать все доступные ядра". Я бы сказал, что в таких условиях это вполне баг.
Честно говоря, не понял о каких последствиях речь. Реализация ведь и так есть, просто спрятана внутри компилятора, а не стандартной библиотеки. Если её перенести, то почему станет хуже?
Предположу, что логика такая: если на результате функции висит
#[must_use]
, то она (скорее всего) чистая. Но да, сравнение слегка странное.Не очень в теме, но в расте стандартную библиотеку и компилятор не одни и те же люди делают?.. Версионируется оно точно вместе. В целом я согласен, что библиотечная реализация лучше, но в данном конкретном случае разница не кажется принципиальной. Плюс есть подозрения, что такая "магическая" реализация — это последствия поздней стабилизации макросов, когда раст 1.0 уже был, а свой
format!
написать ещё было нельзя.Дык, (быть готовым) читать в итоге придётся всё равно все возможные варианты.
Ну ладно, не буду спорить. Похоже я не могу представить как это когда "просто хочется функциональщины". (:
Просто мне кажется, что множества любителей динамической и статической типизации не очень сильно пересекаются. Опять же, в моём понимании, лисп (тем более Common Lisp, о котором шла речь) — это, в первую очередь, макросы и "гибкость".
О каких языках речь? Go довольно часто сравнивают с растом, но последний настолько же ООП, как и Go. Практически весь мейнстрим ООП-шный — это да, но тоже не вижу связи между ООП и дженериками.
Не минусовал, но попробую предположить откуда такая реакция. На мой взгляд языки чуть ли не максимально разные, даром что оба принято называть функциональными. То есть, вопрос звучит примерно как "питон или С?" — в большинстве случаев такой выбор просто не стоит, он определяется предметной областью и личными предпочтениями. Опять же, мы ведём это обсуждение в блоге компании, которая топит за статическую типизацию.
P.S. Обычно такое негодование ещё минусов собирает. (:
А почему размер проекта имеет значение? Если бы код писался на С++, а не на расте вопрос всё равно возник бы? Ну или можно вывернуть другую сторону: "зачем использовать С в таком небольшом проекте, разве асма недостаточно?"
Признаюсь честно, я предвзят, но спрашиваю тоже без критики и агрессии. (:
Так-то и в основном потоке панику можно перехватить.
Да, но с оговорками. Если нет ансейфа, то UB действительно не случится, но и тогда программа может оказаться в разломанном состоянии. Если код написан грамотно, то такого не случится, но в нормальном коде и анврапов особо не будет.
Тут два момента. Во первых, соглашения — если привыкнуть, то за
unwrap
/expect
глаз цепляется не хуже, чем заunsafe
префикс. В этом плане хуже, что паниковать могут другие методы, например, доступ по индексу через квадратные скобки. Это тоже можно порешать, но уже костылём (линтом Clippy). Во вторых, ансейф в расте обозначает конкретное подмножество проблем, а не просто "потенциально опасная операция". Паниковать или допускать утечки — "безопасно".А как это должно выглядеть?
Во первых, не представляю вызов дженериков из другого языка (аналогично с плюсовыми шаблонами). Сюда же хитрости с бороу чекером — это получается компилятор условной джавы должен будет проверять, что растовые функции правильно вызываются? Если всё это вырезать, то останется примерно тот же
extern "C"
, что и в расте сделать можно.Во вторых, у раста нет стабильного ABI.
Почему? Только из-за наличия "std" в названии? Может, конечно, я варюсь в пузыре и сильно заблуждаюсь, но больше похоже на то, что эта библиотека умерла. Из того о чём знаю: растовая libp2p изначально использовала как
async-std
, но и там сделали поддержку токио. О случаях когда токио не поддерживается не слышал.Ну и я привёл ссылки не количество коммитов, то есть "активность разработки", а не число скачиваний. Хотя и по этому параметру у
async-std
всё не очень (1,321,707 недавних скачиваний против 7,417,479 у токио).Всё-таки чуть-чуть эргономичнее из-за атрибутов и прочих мелких удобств. (:
Не думаю, что дело в этом. В расте принято обмазываться вопросиками и код в таком стиле писать не сложно, но это не всегда спасает. Вот предположим, что у нас есть вектор в котором гарантированно не меньше пяти элементов. Можно везде писать
get(2).and_then(…)
, но не хочется. Особенно если функция без этого могла бы возвращать просто значение, а неResult
/Option
. Ответственный человек завернёт такой код в абстракцию и напишет комментарий (и тест заодно). Принципиально эту проблему решают разве что зависимые типы, ну или я чего-то не знаю про хаскель.Мне кажется, что токио всё-таки победил, но сильно спорить не буду. Хотя графики активности говорят сами за себя:
https://github.com/tokio-rs/tokio/graphs/contributors
https://github.com/async-rs/async-std/graphs/contributors
Просто из любопытства: можно пример нескольких более-менее популярных библиотек, которые не поддерживают токио?
Кажется, что tracing решает эту задачу.
Ну если так говорить, то в чём разница с вызовом
std::abort
внутри сторонней библиотеки?.. По большому счёту, "внезапный unwrap" — это баг. Да, язык от всех проблем не защищает, увы.Разве?.. Вижу вот такое:
А в С ряд операций (включая сдвиг влево) с знаковыми целыми может приводить к UB.