All streams
Search
Write a publication
Pull to refresh
68
0
Владимир @Googolplex

Software engineer

Send message
    let max = rs.iter().fold(
        0,
        |acc, ref item|
        if item.name.len() > acc { item.name.len() } else { acc });

вполне заменяется на
    let max = rs.iter().map(|item| item.name.len()).max();

И ref у вас лишний — item и так будет, скорее всего, ссылкой потому что используется iter(), но даже если и нет (если iter() на ResultSet'е возвращает значения, а не ссылки), то ref бессмысленнен — item будет передан в замыкание по значению в любом случае.

И ещё, вместо разбора аргументов программы вручную я бы посоветовал воспользоваться какой-нибудь библиотекой, вроде docopt. Бонус docopt — читабельный хелп к программе.
Ну да, в этом вы правы. Тем не менее, это не curl | sh, который к тому же ставит файлы без ведома менеджера пакетов (хотя конкретно в случае multirust всё достаточно неплохо, и там есть унинсталлер).
В некоторых дистрибутивах линукса есть пакеты multirust, например, в арче это multirust из AUR. В Homebrew на маках, насколько я помню, формула для multirust тоже есть.
Вместо FromStr::from_str(x) лучше использовать x.parse(). А вообще — спасибо за статьи, здорово, что подобные туториалы появляются и на русском тоже.

Кстати, а почему INI а не TOML, в общем-то, практически общепринятый в коммьюнити Rust?
Мне кажется, что для работы с такими связками сервисов типа nginx+php-fpm или подобного имеет смысл использовать docker-compose. Пишется простенький yaml-файл, затем docker-compose up, и всё, сервисы запущены и соединены.
Кстати, если вас интересуют более глубокие вопросы относительно Rust'а, то вы можете почитать Rustonomicon — ещё одну официальную книгу по Rust. Она пока ещё не закончена, но работы идут.
Ну полной заменой C стать не сможет ничто, но писать достаточно низкоуровневые программы, в том числе для микроконтролеров, на Rust вполне возможно)
Privately здесь не значит «в тайне», это значит «лично». Персональные лицензии можно использовать где угодно и когда угодно, только не одновременно в двух местах.
+1 к jemalloc. Например, он вполне успешно используется в качестве дефолтного аллокатора в языке Rust, на всех платформах вплоть до Windows XP.
Стоит отметить, что эта статья немного устарела. В Rust 1.0 и последующих версиях (и даже немного раньше 1.0) по умолчанию значения не копируются, а перемещаются, даже если тип содержит только Copy-данные внутри себя. Чтобы тип был копируем, нужно явно реализовать трейт Copy для него, например, с помощью #[deriving(Copy, Clone)] (реализовать также Clone нужно потому что Copy наследует Clone). Поэтому маркера NoCopy больше не существует.
Очень плохо, если модели «купить»-«обновить по желанию» не станет совсем. Мне не нужно ничего, кроме самой IDEA Ultimate, и в этой новой модели мне потенциально придётся платить в полтора раза больше. Я вижу на странице, что для существующих владельцев лицензии годовая подписка стоит дешевле, но в любом случае сам формат подписки мне не нравится — я не хочу, чтобы мой основной инструмент зависел от каких-то там подписок. Что если у меня не будет возможности продлить её? Я не смогу тогда пользоваться средой вообще? Но это же просто нонсенс.

Если вы хотите позаботиться об удобстве пользователей, которые используют много продуктов, почему бы вам не оставить обе модели?
Но тут есть тонкий момент: большинство айтишников действительно хорошо владеют английским — но только для чтения. Когда нужно написать понятный и емкий комментарий, у многих случается пробуксовка: одно дело бегло читать статьи, новости и книги, а совсем другое — писать самому.

Это интересно, но если начать активно пользоваться Stackoverflow в качестве отвечающего, уровень письменного английского резко повышается. Заметил это на собственном опыте — с тех пор, как я начал активно отвечать на вопросы, писать на английском стало значительно проще, и результат в плане грамматики и прочего — гораздо лучше. Иногда смотрю на свои старые вопросы-ответы там и удивляюсь, неужели я это писал :)
Отлично, спасибо)
В «фитнес-трекеры» входят другие умные часы, типа Pebble?
Это не совсем «обычные структуры/классы», знание о них заложено в компилятор. Например, в случае с трейт-объектами это не обойти никак, потому что в трейт-объектах дополнительная информация — это указатель на vtable, который знает только компилятор. Я думаю, что, теоретически, срезы, которые содержат дополнительную информацию о длине, можно было бы реализовать в сторонней библиотеке, но на данный момент срезы также встроены в язык. То, что лежит в std::raw — это совместимое представление толстых указателей в виде структур, но это не значит, что эти структуры на самом деле используются.

Да, программист может определять свои DST. Например, Path и CStr из стандартной библиотеки — это типы с динамическим размером. Однако на данный момент возможности по созданию DST сильно ограничены, и их реализация не очень, скажем так, приятна глазу. По факту, можно создавать и использовать срезоподобные DST (как вышеописанные Path и CStr). Возможно, можно как-то заюзать этот механизм для сохранения собственной информации. Чего-то большего пока что сделать нельзя, например, нельзя как-то описать толстый указатель с дополнительной информацией в виде собственной структуры, но, я думаю, кто-нибудь может написать RFC по этому поводу, и, возможно, что-то такое будет в будущем добавлено в язык. Пока что, насколько я понимаю, особой необходимости в этом нет.
stepik777 всё правильно объясняет.

В большинстве языков, в частности, и в Rust, типы так или иначе имеют фиксированный размер, который известен компилятору. Примитивные типы, конкретные структуры, фиксированные массивы и прочее — их размер, т.е. необходимое для них число байт, всегда известны.

С другой стороны, существуют типы, размер которых на этапе компиляции неизвестен точно. Например, это «абстрактный» массив — т.е. некоторая последовательность элементов одного типа, но с неизвестной длиной. Другой пример — тип, объединяющий все типы, реализующие какой-нибудь трейт. Например, если Display — это трейт, то Display в контексте типа обозначает любой тип, реализующий этот трейт. Понятно, что потенциально любой тип может реализовывать трейт, поэтому размер таких «объединяющих» типов тоже неизвестен.

Типы с неизвестным размером можно использовать только при выполнении двух условий:
  1. доступ к их объектам осуществляется только через указатель;
  2. вместе с указателем должна храниться какая-то дополнительная информация, позволяющая «обойти» статическое незнание конкретики о типе.


Первое условие нужно, потому что вы не можете использовать объекты типа с неизвестным размером по значению — для этого компилятору придётся выделить память на стеке, но как её выделить, если нужный размер неизвестен? Размер же указателя известен всегда.

Второе условие нужно, потому что, не зная дополнительной информации о конкретном значении, вы не сможете его использовать. Например, в случае с массивом вам необходимо знать его длину, иначе вы не сможете безопасно получить элемент по его индексу. В случае с трейт-объектом вам нужно знать, метод из какой именно реализации трейта необходимо вызвать. В случае с массивами дополнительная информация — это длина массива, а в случае с трейт-объектами — это таблица виртуальных методов. В Rust эта информация хранится непосредственно в объекте-ссылке/указателе, поэтому ссылки/указатели на типы с динамическим размером в Rust называются fat pointers, толстыми указателями.

Например, возьмём тип &[i32] — срез i32. Это ссылка на тип с динамическим размером [i32]. Обычно ссылки реализуются в виде указателей, например, &i32 на самом низком уровне представляется в виде одного 8-байтного или 4-байтного числа. Но &[i32] — это толстый указатель, и он состоит из двух чисел: указателя на начало массива и длины этого массива. При создании &[i32], т.е. при взятии ссыли на массив и преобразовании её в срез, информация о длине исходного массива сохраняется внутри толстого указателя.

&Display — это трейт-объект для трейта Display. В переменной такого типа может храниться указатель на любой тип, который реализует трейт Display. Однако для того, чтобы такую переменную можно было бы использовать, нужно вместе с указателем на значение хранить ссылку на таблицу методов Display, которые реализует тип, значение которого лежит в этой переменной. Поэтому &Display — это толстый указатель, который состоит из указателя на значение и указателя на таблицу виртуальных методов для типа этого значения. При создании ссылки на объект и преобразовании её в трейт-объект указатель на таблицу виртуальных методов сохраняется внутри толстого указателя.

В модуле std::raw лежат структуры, описывающие толстые указатели для разных видов DST. Эти типы можно напрямую преобразовывать (с помощью mem::transmute(), аналога reinterpret_cast из C++) в ссылки на типы с динамическим размером, т.е., например, можно преобразовать std::raw::Slice в &[i32] и наоборот.

Что касается изменений именно в данном релизе, то теперь можно сказать, что типы с динамическим размером поддерживаются компилятором (практически) в полном объёме. Например, можно создавать умные указатели, аналогичные Box из стандартной библиотеки, которые будут прозрачно работать с DST, т.е. автоматически становиться толстыми указателями, если они используются для DST. Раньше этого было сделать нельзя.
И последнее — поиск в гугле по запросу «rust string to str» в первых ссылках даёт вот этот вопрос и ответ на stackoverflow, где объясняются все вышеописанные варианты (хоть и название вопроса немного не то).
И ещё, to_string() не рекомендуется использовать для преобразования &str в String потому что он несёт накладные расходы — он использует механизм std::fmt вместо того, чтобы напрямую создать новую строку и скопировать байты. Поэтому лучше использовать to_owned() (если целевой тип неизвестен) или into() (если известен).
Очень плохо, что в документации as_str() не написано, почему он unstable. Он таков, потому что, вполне вероятно, он будет задепрекейчен. Вероятно, имеет смысл создать ишью в трекере Rust на эту тему.
На самом деле преобразование String в &str делается очень просто. Во-первых, String реализует Deref<Target=str>, поэтому достаточно просто взять адрес от разыменованной строки или положиться на deref coercion, если целевой тип известен:
let s: String = "hello world".into();
let ss = &*s;  // ss: &str

let ss: &str = &s;  // deref coercion, потому что тип известен

А поскольку String реализует Deref<Target=str>, а str реализует трейт Index<Range>, то можно воспользоваться slicing syntax:
let ss = &s[..];

Хотя использование deref coercion более идиоматично.

Information

Rating
Does not participate
Location
Santa Clara, California, США
Date of birth
Registered
Activity