Pull to refresh

Comments 36

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

Я понимаю, что речь идет исключительно о вре́менном даунгрейде &mut до &. Однако, не знакомый с Rust человек может подумать, что это обычное использование неконстантных объектов в константном контексте.

Имхо, этот момент стоило бы пояснить подробнее.
Ну и перевод «must not outlive» как «не должна пережить», как мне кажется, не делает достаточного акцента. Может показаться, что программист должен сам это контролировать, тогда как на деле контролирует и запрещает такое компилятор.

Я бы написал «не может пережить».
Заглавная картинка некорректна. Текстом дано определение круга, а нарисована окружность, почему-то подписанная кругом.
Ну, почему сразу некорректна. Внутри белый круг, граница круга — окружность. Просто несколько двусмысленна.
Еще и в квадрате такого же цвета, что сбивает с толку.
Квадрат подходит под определение круга, если использовать манхеттенское расстояние.
Отличная статья, отличный перевод!
Люблю картинки)
Я хотел освоить rust, открыл его hello world и он меня очень смутил. Чуть более сложный пример, где требуется ввести имя и программа его печатает. Там задаётся мутабельная строка, потом передаётся процедуре чтения. Но во всём этом меня смущает, что мутабельная строка инициализирована пустой строчкой. Зачем? Если процедура сама заполняет строку, то зачем ей давать какой-то готовый объект, пусть модифицирует ссылку. Каких-то разумных предположений я не смог придумать и отложил раст в долгий ящик.

Не видел этот пример, так что не скажу почему автор написал именно так, но никто не запрещает создать строку напрямую:


let mut abc = String::new();

Это будет действительно немножко эффективнее чем инициализация пустой строкой:


let mut abc = String::from("");

Но может автор хотел заодно показать этим примером, как можно создать не только пустые строки, но и с заданным текстом.
Если очень сильно заботится о производительности, то можно предположить сколько текста будет на входе и выделить память заранее:


let mut abc = String::with_capacity(10);
UFO just landed and posted this here
> Ссылка не может быть сама по себе, она должна на что-то ссылаться

А что в rust не бывает null?
За пределами unsafe не бывает.
Вместо него есть Option с гораздо более явной семмантикой, чем null.
Option — это вроде из функционального мира. Там вообще не принято передавать мутабельные аргументы по ссылкам, чтобы в них записывали данные, там обычно функция возвращает все нужные данные кортежом.

А чем Option не вписывается в приземленную императивщину? Лучше передает намерение писавшего код, все такое.

UFO just landed and posted this here
Так сделай ссылку на нулевой указатель
Ссылка может быть на объект. Аналог в Rust есть — Option<Box>. По факту это именно указатель. Если он 0 — None, нет — Some<Box>.
Всё есть объект. Указатель — тоже
сделай ссылку на нулевой указатель

let a: *const i32 = std::ptr::null();
let b: &*const i32 = &a;

но это вообще несколько другое.

Бывает, но только в строго оговоренных местах. Не в hello, world.

Собственно null — это одновременно великая и ужасная вещь. Именно когда разработчики Java «сдались» и сделали так, что обьявлять возможность кидания NullPointerException стало не нужно вся хвалёная «безопасность» «свернулась в трубочку и стекла на пол». Я не видел ни одной программы на Java сколько-нибудь приличного размера, которая бы не падала из-за того, что кто-то где-то таки кинул NPE и он бы не улетел далеко за пределы того модуля где был порождён (он может быть пойман и завёрнут в пять обёрток, но сути это не меняет).

Сможет ли эту проблему решить rust — неизвестно, пока на нём программ в миллионы строк никто не писал. Но попытка достойная.
Ну точно так же можно «не глядя» вызывать get() у Optional, и так же будет пролетать NoSuchElementException через всю программу.
Вопрос будет в количестве этих Optional. Разница в том, что в Java — любой объект может отсутствовать, а потому понять нужно проверять на null или нет нельзя. В rust же предполагается что большинство обьектов таки не будут описываться как Optional и, соответственно, небольшое количество Optional — будет проверяться.

Как оно будет на практике — посмотрим.

К аргументу khim добавлю, что этот get (на самом деле, unwrap) придётся писать, а это дополнительные телодвижения и это хорошо. Сразу приходится задумываться: а может тут не unwrap нужен, а например unwrap_or.

А как вы планируете избавляться от null в джаве? Что будет записано в объекте при его выделении? Не будете же инициализацию пихать в garbage collector? Нет, сборщик мусора, он же управитель памятью, сделает вам пустой объект, где все ссылки забиты null-ами и дальше уже на этапе инициализации они будут переписываться на верные значения. Или останутся null, если произойдёт какая-нибудь исключительная ситуация
А как вы планируете избавляться от null в джаве?
Я не предлагаю от него избавляться. Я предлагаю избавляться от Java. Ибо все преимущества ради которых заплатили весьма и весьма немалую цену оказались «пшиком». Безопасности нет, переносимости нет, для того, чтобы получить приличную скорость нужно, фактически, реализовывать «своё» управление памятью, размещая обьекты в массивах и самостоятельно отмечая — где живые, где мёртвые.

При этом ещё и варианта сделать как в большинстве скриптовых языков («выйти» в C и там всё реализовать эффективно) — в общем тоже нет, так как JNI — штука весьма и весьма своенравная и не очень эффективная.

Нет, сборщик мусора, он же управитель памятью, сделает вам пустой объект, где все ссылки забиты null-ами и дальше уже на этапе инициализации они будут переписываться на верные значения.
И это — очередное 100500е место, где сборщик мусора мешает сделать нормальный язык. Возникает вопрос: а оно точно надо? Мы точно получаем выигрыш из-за того, что не используем разного рода scoped_ptr'ы или shared_ptr'ы, а используем «модный» «полноценный» сборщик мусора?

Обидно то, что мы теперь с этим убожеством связаны на многие годы, так как эта каракатица поселилась в самом сердце Android'а…
UFO just landed and posted this here
> он null-safe, все места из которых может вылететь NPE определяются статически.

А пруфы есть? Система типов java, насколько я помню, не слишком-то и sound, и вряд ли надстройка способна это изменить
UFO just landed and posted this here
> Есть

А дайте ссылку на статью
Вот прямо тут есть чудесная статья, которая показывает, что заявление «предоставляет очень неплохой интероп с Java и он null-safe» всё-таки несколько преувеличено. Kotlin — предоставляет неплохой интероп с Java ИЛИ (а не и!) он null-safe.

Никто не спорит с тем, что поверх Java-машины можно водрузить всё, что душе угодно (в качестве безумного варианта: водрузите JPC поверх вашей JVM — и получите любой язык, с любыми свойствами), но вот сохранить при этом совместимость с Java — уже не получится. Или — или, на выбор.
Дело даже не в наличии/отсутствии null.
Ссылки — это инструмент контролирующий совместный доступ к памяти, поэтому null для ссылки — в принципе лишён смысла.
Если нет переменной, то не нужна и ссылка.
При этом неинициализированные переменные (заранее объявленные) вполне допустимы, компилятор контролирует порядок исполнения и не даст скомпилировать код, читающий переменную до инициализации.

Другой момент — каждый раз создавать строку в процессе преобразований — не самый эффективный паттерн, хотя, конечно, так можно (например, функция будет каждый раз создавать String и возвращать её).
Но для ввода-вывода API строится так, что пользователь сам создаёт буфер и передаёт его для заполнения в функцию. Кроме прочего, это позволяет реализовывать эффективную конкатенацию и в случае необходимости переиспользовать буфер, без повторного выделения памяти в куче (достаточно «дорогая» операция).
При этом буфер может быть произвольного типа, лишь бы он реализовал соответствующий необходимый типаж Read или Write.
При таком подходе весь контроль над тем, что на самом деле будет происходить, — в руках программиста. И это достаточно важно для языка, предназначенного быть эффективным и позиционируемого как низкоуровневый/системный.

Не спец по Rust, но то что копирование или перемещение зависит от типа при сходных действиях, мне очень не нравится ибо смотря на выражение let a = b я не уверен что произойдет c переменными a и b.

смотря на выражение let a = b я не уверен что произойдет c переменными a и b
Ну почему же? Ясно что окажется в a, а вот останется ли что-нибудь в b — уже не так ясно, но это и не очень страшно: если обьект простой и копируемый, то его ненужную копию «изведёт» оптимизатор, а если сложный — и некопируемый, то попытка его использовать — это ошибка, компилятор вам не даст ничего напутать. Проблема будет если обьект копируемый, но сложный и его копировать дорого — так просто лучше не делать.
Sign up to leave a comment.

Articles