Comments 30
Спасибо, интересно. Как вы оцениваете русскоязычные переводы некоторых из перечисленных вами книг? В частности, вот этой: https://www.amazon.com/Programming-Rust-Fast-Systems-Development/dp/1492052590
У меня есть русский перевод книги про атомарность Мары Бос (https://www.chitai-gorod.ru/product/rust-atomarnosti-i-blokirovki-3060006). К сожалению, есть ошибки в переводе смысловые, чтобы их понять и в уме исправить приходится некоторые абзацы перечитывать по несколько раз. Вообще предпочитаю читать в оригинале, т.к. технический английский не такой сложный, как литературный.
Полностью с вами согласен - сам предпочитаю оригиналы. Что касается упомянутой мной книги, то ее перевод (https://dmkpress.com/catalog/computer/programming/978-5-97060-236-2/) мне показался вполне нормальным, исключая забавные ляпы. Например, на странице 60 в одном (!!!) абзаце для управляющего символа escape приводятся два кода: 27 (правильный) и 37. Очевидно, что это ошибка набора. Для опытного программиста это не проблема; для начинающего - засада
Мне очень понравилась книга Zero To Production in Rust. Прям пошаговый пример создания приложения
Поддержу, хорошая книга. Если кто-то бекендщик, хочет изучить rust и любит подход изучения "сверху вниз", то это будет хорошая входная точка: можно находиться в знакомых абстракциях и в целом понимать что происходит, походу дела выписывать вещи языка, которые использовались и продолжать погружение от них, от часто используемых до редко.
Предпочел бы меньше эмоций и больше примеров. В частности, что не получалось на PHP, примеры ошибок, количественные оценки качества продукта (количество ошибок и т.п.), как быстро пишут код в сравнении 2х языков. И так далее.
А тут удивительно мало конкретики и опыта.
Asynchronous Programming in Rust: Learn Asynchronous Programming by Building Working Examples of Futures, Green Threads, and Runtimes не плохая книга, для общетеоретической подготовки. Читал в оригинале, читается легко.
Hands-On Concurrency with Rust: Confidently Build Memory-safe, Parallel, and Efficient Software in Rust
То же интересная книга, хоть и более старая.
В тексте много сравнений с java, но как насчёт kotlin?
Rust вообще системный язык общего назначения, его и надо с ними сравнивать - C, C++, Pascal, Zig, Odin, Golang, Nim, не понимаю почему вообще сравнивать с Java или Kotlin а тем более PHP, тут только одно может быть сравнение на Kotlin вы найдете работу, на Rust нет, только если не тимлид и прям упретесь перед начальством что это вот пишем на Rust и всё тут
" Те кто не освоил главу №4 будут играть в замечательную игру «Уломай компилятор скомпилировать твой код». Все правила управления памятью, которые делают rust таким мягким и пушистым, заставляют вас думать по другому об устройстве вашей программы. "
@Nurked :)
Когда пишешь сверху вниз, можно хорошо прописать интерфейсы и типы. Но если снизу вверх, проект постепенно сшивается из кусков, сами интерфейсы видоизменяются во времени. Здесь была серия статей про использование Rust в геймдеве и возникающие проблемы упомянутого класса.
Не в упрек языку. Но очень редко плюсы бывают без сопровождающих минусов и соответственно наоборот.
Приложение на Rust ведет себя тут как приложение на C/C++ — выделяет и освобождает память когда нужно.
Что за такой волшебный несуществующий язык C/C++? C не делает этого никогда. Про C++, совершенно другой язык программирования с похожим синтаксисом C, можно сказать то же, пока не реализуешь конструкторы-деструкторы, которые будут вызываться только для автоматических переменных. Автор, по-моему, не знает ни того, ни другого, но сравнивает Rust с ними.
Про C много читал, разные книги, много исходников смотрел. Про C++ много читал, знаю меньше. На обеих не пришлось писать, к сожалению. Начал больше 20 лет назад сразу на Java.
Да, вы правы, конечно, я опечатался, спасибо что заметили. Убрал про C, в нем, конечно, нет деструкторов и нужно ручками "free" вызывать.
Кто нибудь коротко обьяснит - в расте управление памятью сделано через подсчет ссылок и всякого рода смартпоинтеров, или там как то все совсем по другому? А если через подсчет ссылок то как решена проблема циклических ссылок друг на друга?
Проблема циклических ссылок решается сборщиком мусора , которого в Rust нет.
В Rust создание циклических зависимостей достаточно сложный процесс, чтобы на практике этим заниматься только когда действительно необходимо.
Попробую объяснить просто на пальцах. Можно по-разному, гибко, рассказываю от простого к сложному. Компилятор Rust консервативный, иногда перегибает палку и его нужно учиться обходить:
1) "Объекты" создаются обычно в стеке, но могут "взять" себе память в heap.
2) У "объектов", которые "взяли" себе память в heap, обязательно в конце области видимости или в конце их владения (похоже на move-семантику в С++, но безопасная, проверяемая компилятором) вызывается деструктор - компилятором. Компилятор сам вставляет его вызов в бинарку, но в исходниках вызова не видно. По сути похоже на RAII из С++ и по сути такие объекты есть простые smart-pointers (Box).
3) Есть продвинутые "объекты" - smart-pointers, которые не только берут память в heap, но и могут "множится", в т.ч. между потоками и последний такой "объект" удаляет выделенную в heap память. Да, это подсчет ссылок, как и в Swift. Все это проверяется компилятором тоже, безопасно. Это работает с большими издержаками, чем в п.2, поэтому необязательно (Rc, Arc).
4) Можно, через indirection в heap, сделать связанный список, чтобы каждый его элемент был известного для расположения в стеке размер. Так до определенной степени поддерживаются рекурсивные структуры данных типа известного списка "Cons(2):Cons(1)::Null", деревьев и т.п..
5) Когда этого не хватает и нужно больше гибкости, можно динамически связывать "объекты" ссылками в графы через жестко контролируемую компилятором технику внутренней мутабельности (UnsafeCell <- RefCell) и его рантайм контролем ссылок. По умолчанию, ссылки всегда ведут на живые "объекты", может быть одна эксклюзивная (можно менять через нее) или несколько для чтения, но можно это делать динамически и если создашь случайно две эксклюзивные, то программа остановится (контролируемый "крэш" с вызовом деструкторов вверх по стеку - "panic"). Я думаю, это поможет сделать циклические связи в графе "объектов". Не пробовал, если честно.
6) Если не хватило гибкости, всегда есть блок "unsafe", raw-pointers и из них можно что и как угодно собрать, в т.ч. ссылки какие нужны. Может быть придется делать свой локальный сборщик мусора. Но лучше попробовать все способы выше.
Управление памятью реализовано через владение (ownership). Компилятор на этапе _компиляции_ анализирует код и сам вставляет вызовы free (условно) в то место, где владелец данных (переменная) выходит из скоупа (то есть гарантированно больше никто не может ссылаться на данные).
Контейнеры с подсчётами ссылок есть, но используются не часто.
Управление в расте реализовано так же как в плюсах - с использованием RAII на деструторах (они там trait Drop называются), на которых, в частности, смарт поинтеры со счётчиком ссылок работают. А чтобы тяжелее было получить use after free и прочие известные в плюсах штуки, в раст завезли borrow checker - набор правил работы со ссылками, которые проверяются компилятором и не дают случайно выстрелить в ногу.
"Я пишу код с 12 лет и системно занимаюсь коммерческой разработкой с начала нулевых. В основном это Java, Python, PHP, JavaScript и, в последние годы, это Rust. Приходится писать, в основном, mission‑critical системный код..."
Ох уж эти мамкины разрабы с 12 лет. На PHP он пишет mission-critical системый код. Что ещё про PHP мы не знаем?
"Про C много читал, разные книги, много исходников смотрел. Про C++ много читал, знаю меньше. На обеих не пришлось писать..."
"В результате, сейчас, наконец‑то, стало понятно все в деталях, код пишется быстро, задачи решаются легко..." - эти люди, которые вам сказали, что вы пишете быстро и решаете задачи легко - они сейчас здесь, в одной с вами комнате?
Я в принципе, не ожидал ничего нового услышать или увидеть в этой статье и комментах.
Блин, чуваки, иногда язык программирования - всего лишь язык, от того что ты выучишь русский язык, ты не станешь Достоевским, и не станешь писать как Кинг, если выучишь английский. Если ты пишешь как баран, то ты будешь писать как баран свой ужасный код на любом языке.
Я все жду статью про раст от бородатого системного и embedded-разраба, который такой: пишу 20 лет на с, 13 лет на с++, пишу модули для работы с TCP/IP для freebsd, на работе заставили писать на расте, и знаете, вот что я вам скажу...
Это интересно читать, это очень крутой кейс, а не вот эти мамкины программисты с 12 лет. Предлагаю таким разрабам в качестве вступления вставлять в начале статьи ссылку на гитхаб, этого более чем достаточно.
"а не вот эти мамкины программисты с 12 лет" ну не знаю, почему именно мамкины :-) Я еще на Highload регулярно выступаю, если погуглите, видео много. И еще на хабр опубликовал почти 60 постов, по ним понятно, что за проекты и где там "миссион-критикал".
"а не вот эти мамкины программисты с 12 лет" ну не знаю, почему именно мамкины :-) Я еще на Highload регулярно выступаю, если погуглите, видео много. И еще на хабр опубликовал почти 60 постов, по ним понятно, что за проекты и где там "миссион-критикал".
При всех плюсах отсутствия сборщика «мусора» пока, даже в продвинутых Go, С# и Kotlin, он есть, а в Rust — его уже нет. Почему? Потому‑что в Rust сделали очень продвинутый, вобравший в себя множество современных знаний о языках программирования (и известных проблем), компилятор, использующий афинные типы данных (уникальная возможность, о ней в следующий постах), алгебраические «sum/product» типы и «pattern‑matching» по ним, концепции безопасных «shared» и «exclusive» ссылок для оптимизаций ненужных «aliasing» (этой проблеме в современных ЯП не один десяток лет и в Rust ее красиво решили) и строгую систему типов, позволяющую быстро и дешево писать высоконагруженный многопоточный код, работающий со скоростью C/C++ и при этом не «падающий» из за «неопределенного поведения».
"Смешались в кучу кони, люди, колбаса и волчий хер" :D
Начинаете оду расту за отсутствие GC, но это благодаря RAII и деструкторам Drop trait'у, scope'ам и lifetime'ам, и система типов с компилером тут ни при чём, это старо как мир, и не присуще только rust'у. А вот борьба с пресловутым borrow checker'ом как раз выливается в использование Rc/Arc (reference counting), что некоторыми считается аналогом GC (потому что это не-мануальный мемори менеджмент, пусть и не полноценный GC). Афинные и алгебраические типы, паттерн матчинг - это всё для красного словца.
позволяющую быстро и дешево писать высоконагруженный многопоточный код, работающий со скоростью C/C++ и при этом не «падающий» из за «неопределенного поведения».
За наброс на плюсы обидно, наброшу в ответ, напомнив про банальный кейс "rust panics on overflow" :D В плюсах не так много UB, в rust'e своих приколюх хватает, вроде "память течёт? - это не проблема, ведь она не кораптится, значит всё безопасно", и менежмент shared + weak указателей он оставляет на откуп юзеру, благодаря чему люто течёт память в redox и из последнего - в cosmic.
Начинаете оду расту за отсутствие GC, но это благодаря RAII и
деструкторамDrop trait'у, scope'ам и lifetime'ам, и система типов с компилером тут ни при чём, это старо как мир, и не присуще только rust'у. А вот борьба с пресловутым borrow checker'ом как раз выливается в использование Rc/Arc (reference counting), что некоторыми считается аналогом GC (потому что это не-мануальный мемори менеджмент, пусть и не полноценный GC). Афинные и алгебраические типы, паттерн матчинг - это всё для красного словца.
Про качество статьи согласен, нафиг такую рекламу Rust. Но вы и сами набрасываете, и довольно нелепо:
- так в каком языке есть лайфтаймы, старые как мир?
- reference counting никак не может считаться аналогом GC, т.к. выполняется сразу за счет деструкторов и RAII.
- магии не существует, и все языки без GC активно используют reference counting (особенно С++), так что в этом плохого?
За наброс на плюсы обидно, наброшу в ответ, напомнив про банальный кейс "rust panics on overflow"
Опция overflow-checks для Cargo.toml существует с выхода Rust 1.0, 10 лет назад.
В плюсах не так много UB
В плюсах столько UB, что их полный список невозможно запомнить. Их буквально несколько сотен. Есть даже целые книги, посвященные UB (https://github.com/Nekrolm/ubbook/, https://pvs-studio.ru/ru/blog/posts/cpp/1129/).
Многие из них крайне не очевидные и не ловятся статическими анализаторами. Санитайзер не поможет в коде, который управляет критически важным оборудованием (АЭС, спутники, самолеты и т.д), т.к. всё уже взорвется/упадёт.
"память течёт? - это не проблема
Это проблема, когда она течет. Но какое отношение это имеет к языку?
Утечку памяти легко организовать через 2 reference counting в любом языке. Предъявляйте претензии к конкретным библиотекам.
И, всё таки, утечка памяти не позволит кому то совершить взлом на лярд долларов, в отличие от UB.
Так как можно сократить путь? Начать я понял с какой книги, а параллельно с ней нужно что-то изучать?
Про Rust — просто. Что читать в каком порядке?