Комментарии 68
И вобщем всё это круто, но никому не нужно, кроме полтора задрота, которые на нем работают и 2к его изучающих, что в скором времени бросят это гиблое дело, как и десятки других языков.
Потому что :
Не хватит времени чтобы изучить какой-либо язык на том уровне, который требуется для работы, т.к. всё слишком замусорилось, вагоны библиотек, паттернов и т.д
Изза обилия дублирующих по функционалу языков и библиотек к ним, наблюдается сильный разброс требований
Индустрия плавно загибается, новых специалистов все меньше, удав начал есть себя с хвоста
Сейчас просто все смешалось: тяжелое наследие прошлого, текущий мейнстрим и ростки будущего. Насколько эти ростки жизнеспособны — покажет история, но кто-то уже сегодня их принял и к ним примкнул.
Мне недавно надо было написать генератор флуда в journald для оценки его производительности. Питон отвалился (кратно медленнее journald), писать на Си было многообещающе. Написал на Rust'е, пять строчек. 1:2 по нагрузке (50% моего приложения на 100% journald). Совершенно тривиально и просто. Для меня это такой добротный инструмент второго ряда, если медленные языки не справляются.
По-моему, у раста неплохое настоящее и очень светлое будущее.
Насчет borrowing Rust обычно прав. Поначалу бесит, но потом понимаешь, что компилятор нашел в коде неочевидную архитектурную ошибку, которую на C++ я бы прозевал.
Так и есть, в начале тяжело. Но через полгода-год практики уже перестаешь замечать, что пишешь на языке с BC, а не с GC.
Зато потом приходишь в другие языки, и такой: ааааа где проверка типов? ааааа здесь можно оставить висящую ссылку! аааа нуллпоинтер!
И так далее.
Кстати, после Rust'а я начал лучше писать на Питоне. Когда используешь модель Rust'а вне Rust'а, то часть бенифитов сохраняется. Тебя больше никто не поправляет на ошибках, но если их не допускать, получается хороший код.
Боюсь, что с циклами это вообще фундаментальная проблема, да и утечки это не так уж смертельно, на самом деле.
Я бы добавил, что утечка утечке рознь.
Из моей практики, циклы в структурах, о которых в первую очередь вспоминают, это ничтожная часть всех утечек.
Куда более распространенная в си ситуация связана с «беспорядочной половой жизнью» указателей и спонтанные, неформализованные и нигде не задокументированные контракты владения вида:
- память освобождает вызывающий
- память освобождает вызываемый
- указатель нужно скопировать себе, передавать его как есть (работает как дескриптор)
- содержимое указателя нужно скопировать себе, передавать копию по значению/указателю
- память статическая, не копировать, ссылаться напрямую
и т.д.
Притом что во всех случаях интерфейс, утрируя, может выглядеть как void foo(void* ptr)
.
При таком подходе утечь память, прозевав, кто же все-таки должен ее прибирать, — раз плюнуть.
Вот здесь можно оценить состояние экосистемы https://www.areweguiyet.com/
Оно не то что бы очень хорошо обновляется. Я бы скорей посоветовал обзорные статьи вроде https://dev.to/davidedelpapa/rust-gui-introduction-a-k-a-the-state-of-rust-gui-libraries-as-of-january-2021-40gl
В чем? В обилии экспериментальных UI проектов? Так это не потому что хорошего нет, а потому что семантика Rust отличается от больишнства императивных языков и ссылочная лапша UI кода не ложится естественным образом на нее. Вот люди и пробуют варианты от реактивных моделей до линз с тем чтобы подобрать идиоматичную абстракцию.
Или может быть вы разочарованы в том что Microsoft официально поддерживает WinAPI для Rust?
Поэтому я все эти тёрки «лучше» / «хуже» плохо воспринимаю. Народ здесь попался какой-то обидчивый («забирай свои игрушки и не писай в мой горшок!»). Каждый работает в том, что лично ему больше нравится и больше подходит. Обсуждать, в общем-то, и нечего.
Вы забыли упомянуть самые главные особенности: то как раст работает с памятью и какие проблемы этим самым решает.
Зачем нужен let, при этом контстанты декларируются явно const. Всё что не константы, должно быть mutable, но для раста это не так. Так что кодеру приходится думать о том, что и где у нас мутирует и почему. Подозреваю, правила видимости переменных в расте слишком либеральны.
Работа со строками как с массивами байтов мягко говоря уже как-то старомодно. Должна быть поддержка utf8/utf16 с определением длины таких строк в символах. Так что в целом довольно коряво, но для написания кода оно несколько лучше с.
Зачем нужен let, при этом контстанты декларируются явно const. Всё что не константы, должно быть mutable, но для раста это не так.
Сюрприз: ещё и static
есть. Язык всё-таки системный и это различие бывает важно. Ну а то, что "переменные" не изменяемые по умолчанию на мой взгляд очень удобно.
Должна быть поддержка utf8/utf16 с определением длины таких строк в символах.
Поддержка utf8 есть, а вот utf16 — это как раз и есть "старомодно".
Подозреваю, правила видимости переменных в расте слишком либеральны.
Это как?
Константы ≠ иммутабельные переменные. Константное значение может быть (и будет) вычислено в compile-time и жёстко зашито в бинарник. Если мы спрашиваем число у пользователя и кладём в переменную, то она не может быть const. Даже если никогда не собираемся её обновлять. Невозможно захардкодить значение, которого мы не знаем.
Так что кодеру приходится думать о том, что и где у нас мутирует и почему
Весь язык построен на borrowing rules, которые требуют, чтобы на один объект не было больше одной мутабельной ссылки в каждый момент времени. Это довольно строгое ограничение, которое компилятор должен суметь доказать в compile-time. Соответственно думать и помнить об этом приходится, таков язык. Он вообще не позиционируется как простой.
Должна быть поддержка utf8/utf16 с определением длины таких строк в символах.
Обычный вопрос для юникода — а что именно считать одним символом? Не все знакомы с особенностями юникода, поэтому в corner-cases ожидания людей частенько не совпадают с реальным поведением. Соответственно вылезают неожиданные баги, которые язык стремится предотвратить. Явное лучше неявного и всё такое. Однако для простых случев в стандартной библиотеки есть s.chars()
, но у него в документации явно сказано, что он может возвращать не совсем что хотелось. Плюс в Книге целая глава посвящена аккуратной работе со строками.
Следующий момент — Rust позиционируется как производительный язык с zero-cost абстракциями. Вычислить длину UTF8 строки невозможно за O(1). Это совсем не совпадает с ожиданием, что длина любой коллекции вычисляется быстро. Поэтому предлагается писать s.chars().count()
— явно создать итератор по символам, полностью его перебрать и вычислить длину.
Не понял аналогии, возможно вы что-то путаете. В языке есть let mut
/let
и есть &mut
/ &
(ссылки). Если планируется менять переменную, то let mut
нужно обязательно указывать, хотя компилятор и так мог бы разобраться. Эта пометка лишь помогает понять человеку, меняется ли значение. При желании, можно всем переменным ставить mut и ничего не сломается. С ссылками дела обстоят немного интереснее, потому что язык требуют от программиста соблюдать некоторые правила.
Они формулируются как-то так: на каждый объект может существовать либо единственная &mut ссылка, либо сколько угодно не-mut. Либо то, либо другое — одновременно нельзя.
Зачем это нужно? В основном, чтобы обеспечивать спокойствие программиста в многопоточных приложениях. С одной стороны, в программе ни один объект не изменяется одновременно из двух мест, а значит не бывает гонок. Вдобавок никто не может наблюдать промежуточное состояние, когда объект изменился только частично и находится в некорректном состоянии.
Эти ограничения могут казаться излишне жёсткими, но на самом деле всё не так плохо. Во-первых, очень часто не нужно менять существующие объекты, достаточно их только читать. Во-вторых, некоторые вещи, например подкючение к БД, можно использовать и по обычной ссылке, несмотря что происходят всякие INSERT INTO и состояние "меняется" — базы данных сами умеют разруливать гонки и им не нужна помощь от компилятора. В-третьих, всегда можно перенести проверки в runtime, используя Arc+Mutex. Они не позволят нарушить правила и сделать гонку данных, но при этом позволяют (плохо) писать практически как на обычных языках.
Простой пример без многопоточности: человек начал итерировать по стандартному списку (vector), для чего взял на него не-mut ссылку. В большинстве других языков, если вдруг кто-то добавит элемент в список, то произойдет либо UB, либо исключение, либо какая-то другая неожиданность. Но чтобы добавлять элементы в список необходимо иметь &mut ссылку на вектор, а компилятор этого не позволит, совсем. Вот таким нехитрым образом потенциальная ошибка нашлась сразу же.
> то let mut нужно обязательно указывать, хотя компилятор и так мог бы разобраться.
Идея заставить программиста соблюдать ограничения путём написания необязательных для работы компилятора синтаксических конструкций
выглядит очень неоднозначно. Очень многое в Rust сделано необычным образом. Но тут практика покажет насколько это жизнеспособно…
2. Моё знакомство с Rust, скажу честно, где-то в общей сложности составляет… гм… пару часов просмотра примеров из учебника...:)))
3. Достоинства реализации многопоточности в Rust после столь краткого знакомства мне трудно.
4. Использовать что-то вроде мьютекса для блокировки объектов однопоточного приложения- довольно экзотическая идея.
Ну, а что касается хорошей реализации unicode, в качестве стандартной библиотеки, то, надеюсь, это со временем и Rust получит.
В Rust Utf-8 строки, просто вы на них смотрите по-умолчанию как на байтовый массив.
Идея заставить программиста соблюдать ограничения путём написания необязательных для работы компилятора синтаксических конструкций выглядит очень неоднозначно.
Необязательность — штука относительная.
Rust проектировался с оглядкой на то, что человек может и будет ошибаться. Обязательность дополнительных деклараций, хоть и не панацея на все случаи жизни, но помогает ловить существенное количество ошибок вплоть до опечаток.
Идея заставить программиста соблюдать ограничения путём написания необязательных для работы компилятора синтаксических конструкций
Если этого не указать явно, а полагаться на вывод компилятора, то возможна очень странная ситуация, когда добавление записи в переменную ломает код в другом месте функции.
Использовать что-то вроде мьютекса для блокировки объектов однопоточного приложения- довольно экзотическая идея.
Для однопоточного мьютексы не нужны.
Зачем нужен let
Потому что есть много сахара, основанного на паттерн матчинге, как пример: if-let, без let наверное можно было бы обойтись, но читаемость была бы сильно ниже.
Всё что не константы, должно быть mutable
Что, по-вашему должно происходить в выражении "x = y" и почему?
Подозреваю, правила видимости переменных в расте слишком либеральны.
Строго консервативны
Должна быть поддержка utf8/utf16 с определением длины таких строк в символах
Какая длина у составных эмодзи и почему вы думаете, что ваш вариант устроит всех?
Про необязательную точку с запятой что-то "резануло глаз".
Дело не в том, что раст и так может понять строку, а в том, что блок выделенный фигурными скобками является выражением и не ставя точку с запятой в последней строке этого блока вы задаете ему значение. И конструкция if является выражением.
На Unix-подобных ОС сделать это можно одной командой:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Упорно не могу понять, почему в куче руководств по разным софтам предлагается установка в обход пакетного менеджера. Когда я ставлю ПО через пакетный менеджер, я знаю, что произойдёт дальше. А когда ставлю через подобный скрипт, то появляется куча вопросов без ответа — куда произойдёт установка? будет ли возможность указать каталог для установки или оно молча улетит куда-нибудь в /usr/local? будет ли оно использовать системные библиотеки в зависимостях или потащит свои бинарники?..
Не хочется быть занудным, но вместо того, чтобы городить костыли, лучше бы разработчики потратили время на поддержку пакетов в популярных дистрибутивах, и все были бы счастливы.
rustup
ставится в домашнюю директорию и все установленное через него тоже сохраняется туда же. Довольно удобно.
Не хочется быть занудным, но вместо того, чтобы городить костыли, лучше бы разработчики потратили время на поддержку пакетов в популярных дистрибутивах, и все были бы счастливы.
Дело в том, что этот костыль умеет не только устанавливать и обновлять раст: он позволяет иметь несколько версий и легко между ними переключаться. Плюс можно зафиксировать разные версии для разных проектов.
В Gentoo, к примеру, у меня 4 разных питона — пакетный менеджер умеет такое делать. Когда для разных проектов нужен определённый питон, то настраивается виртуальное окружение, которое делает симлинк на требуемый системный питон. Не говорю, что для раста надо делать также. Просто один из возможных способов.
Я в общем-то не спорю с удобством системных пакетных менеджеров. Подозреваю, что тут целая совокупность причин.
На ранних этапах развития языка гораздо проще поддерживать один свой костыль, чем заниматься поддержкой пакетов сразу в нескольких дистрибутивах. С точки зрения вводных статей вроде этой проще написать "установите язык вот такой командой", чем расписывать несколько вариантов или, тем более, предлагать самостоятельно разбираться. Тут можно возразить, что для среднего разработчика не должно быть проблемой разобраться, но всё-таки порог входа снижается.
Ну и наконец "найтли" версии языка собираются каждые сутки и опакечивать их нет никакого смысла. При этом "нестабильные" фичи доступны именно в найтли версиях. Про кросскомпиляцию уже сказали рядом — тоже аргумент.
Кстати, rustup умеет работать c установленным из системного пакетного менеджера компилятором.
Можно установить и в систему через пакет — удобно для контейнеров.
А для локальной разработки удобнее в домашнее окружение — несколько редакций, типов сборки и кэш пакетов — переключается и обновляется на лету, не надо глобально систему дёргать.
Я опоздал на неделю со своим комментарием, но всё равно спасибо тебе, автор, за эту статью. Возможно найдётся десяток (или два десятка) молодых пламенных сердца, которые прочитав эту статью решатся проштудировать растбук, которых не испугает страшный borrowck и они поспособствуют росту популярности во-многом хорошего и прогрессивного инструмента.
Для тех, кому хочется проще работать с добавлением зависимостей в Cargo.toml: [cargo-edit](https://crates.io/crates/cargo-edit)
За ковидный карантин я успел перепробовать множество разных языков, остановившись в итоге на Расте.
Была ли в этом множестве Ада?
Как я влюбился в Rust и чего мне это стоило