LINUX.ORG.RU

Rust 1.17

 ,


3

9

Команда Rust рада представить выпуск Rust 1.17.0. Rust — это системный язык программирования, нацеленный на безопасность, скорость и параллельное выполнение кода.

Если у вас установлена предыдущая версия Rust, то для обновления достаточно выполнить:

$ rustup update stable

Если у вас ещё не установлен Rust, то вы можете установить rustup c соответствующей страницы нашего веб-сайта и ознакомиться с подробным примечанием к выпуску 1.17.0 на GitHub.

Что вошло в стабильную версию 1.17.0

Выпуск Rust 1.17.0 в основном вносит небольшие улучшения, преимущественно касающиеся удобства использования. Например, время жизни 'static теперь автоматически подразумевается для констант или статических переменных. При создании константы или статической переменной:

const NAME: &'static str = "Ferris";
static NAME: &'static str = "Ferris";

Rust 1.17 позволит вам больше не писать 'static, так как это единственное время жизни, которое имеет смысл:

const NAME: &str = "Ferris";
static NAME: &str = "Ferris";

В некоторых ситуациях это позволит избавиться от лишних повторений:

// было
const NAMES: &'static [&'static str; 2] = &["Ferris", "Bors"];

// стало
const NAMES: &[&str; 2] = &["Ferris", "Bors"];

Другим подобным косметическим улучшением является «короткая инициализация полей». Подобно ECMAScript 6, который называет это «Сокращение Значения Свойства Объектного Литерала» («Object Literal Property Value Shorthand»), дублирование может быть удалено при объявлении структур, к примеру:

// определение
struct Point {
    x: i32,
    y: i32,
}

let x = 5;
let y = 6;

// было
let p = Point {
    x: x,
    y: y,
};

// стало
let p = Point {
    x,
    y,
};

То есть форма записи x, y будет предполагать, что значения x и y соответствуют переменным с аналогичными именами, находящимися в данной области видимости.

Другое маленькое, но полезное улучшение касается в основном новичков в Rust, которые пытаются использовать +, чтобы соединить две &str вместе. Но это не работает, соединить вы можете лишь String + &str. Поэтому, было добавлено новое сообщение об ошибке, чтобы помочь пользователям, которые совершают подобную ошибку:

// код
"foo" + "bar"

// было
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
  |
note: an implementation of `std::ops::Add` might be missing for `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^

// стало
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
  |
  = note: `+` can't be used to concatenate two `&str` strings
help: to_owned() can be used to create an owned `String` from a string
reference. String concatenation appends the string on the right to the string on
the left and may require reallocation. This requires ownership of the string on
the left.
  |     "foo".to_owned() + "bar"

При использовании сценариев сборки Cargo вы должны указать расположение скрипта в вашем Cargo.toml. Однако, подавляющее большинство людей писали build = «build.rs», тем самым используя файл build.rs, расположенный в корне проекта. Теперь это соглашение поддерживается самим Cargo, и будет использовано по умолчанию, если существует файл build.rs. Мы предупреждали об этом изменении в течение нескольких последних выпусков. Вы также можете использовать build = false для отказа от этого соглашения.

В этом выпуске удалена старая система сборки на основе Makefile. Новая система, анонсированная в Rust 1.15, написана на Rust и в основном использует Cargo для управления сборкой. На данный момент она уже достаточно зрелая, чтобы быть единственной системой сборки.

В рамках этого изменения, пакеты из crates.io теперь можно использовать в системе сборки Rust. Первым был добавлен mdBook, и он теперь используется при сборки нашей разнообразной книжной документации:

Обратите внимание на ссылки на соответствующие репозитории; документы были перемещены из основного дерева. Кроме того, мы добавили четвертую книгу, которая все еще расположена в основном дереве: Книга «Нестабильные возможности Rust». Она описывает нестабильные возможности, содержит ссылки на задачи, связанные с их стабилизацией, и может содержать исходную документацию. Если есть возможность, которую вы хотите увидеть стабилизированной, то пожалуйста, примите участие в ее обсуждении!

Несколько выпусков назад rustup перестал по умолчанию устанавливать документацию. Мы внесли это изменение, чтобы немного разгрузить канал, а также потому, что не все пользователи в действительности хотят хранить локальную копию документации. Однако это создало ловушку: некоторые пользователи не были в курсе, что произошло изменение, и заметили бы это, только если бы у них пропало подключение к Интернету. Кроме того, некоторые пользователи хотели иметь локальную копию документации, независимо от их подключения. Таким образом, мы откатили данное изменение, и документация снова устанавливается по умолчанию.

Подробнее смотрите примечания к выпуску.

Стабилизация библиотек

Был стабилизирован 21 новый интерфейс:

  • Arc::into_raw и Rc::into_raw позволят вам забрать Arc или Rc и получить сырой указатель.
  • Arc::from_raw и Rc::from_raw позволят вам забрать сырой указатель и получить Arc или Rc.
  • Arc::ptr_eq и Rc::ptr_eq возвращает true если оба Arc или оба Rc указывают на одно и то же значение (не обязательно значения, которые сравниваются, равны).
  • Ordering::then позволит вам сцепить два Ordering вместе, и Ordering::then_with позволит сделать это с помощью функции.
  • BTreeMap::range позволит вам итерировать лишь по части BTreeMap, и BTreeMap::range_mut позволит вам сделать это с возможностью изменения. collections::Bound может дать вам еще больше контроля.
  • process::abort будет полностью завершать процесс анормальным образом.
  • ptr::read_unaligned и ptr::write_unaligned аналогичны ptr::read и ptr::write, но без требований к выравниванию.
  • Result::expect_err зеркально подобен Result::expect, то есть работает с вариантом Err, а не с вариантом Ok.
  • Cell::swap аналогичен std::mem::swap, но позволяет вам делать это с &Cell вместо &mut T.
  • Cell::replace аналогичен std::mem::replace, но позволяет вам делать это с &Cell вместо &mut T.
  • Cell::into_inner позволит вам взять Cell, и извлечь его значение.
  • Cell::take позволит вам забрать значение Cell наружу, заменив его на Default::default.

Что касается других изменений, для многих методов Cell<T> требовалось ограничение T: Copy, но теперь это требование значительно ослаблено.

Box<T> теперь реализует более дюжины новых преобразований с помощью From.

SocketAddr и IpAddr также теперь имеют несколько новых преобразований. Раньше вы должны были писать код вроде этого:

"127.0.0.1:3000".parse().unwrap()

Сейчас же вы можете писать
SocketAddr::from(([127, 0, 0, 1], 3000))
// или
([127, 0, 0, 1], 3000).into())

Что позволит удалить ненужный парсинг во время выполнения. Оба варианта примерно одинаково удобно читаются, все зависит от ваших предпочтений.

Обратная трассировка теперь имеет более приятное форматирование, опуская некоторые незначительные детали по умолчанию.

Возможности Cargo

Помимо ранее упомянутых изменений, касающихся build.rs, у Cargo есть еще несколько новых улучшений. cargo check --all и cargo run --package — два отсутствовавших до этого момента флага, которые теперь поддерживаются.

Теперь вы можете игнорировать проверки отзыва SSL. Конечно, по умолчанию проверка все еще производится.

Новое поле в Cargo.toml, required-features, позволяет указать конкретные возможности, которые должны быть установлены для цели, которую нужно собрать. Вот пример: предположим, что мы пишем контейнер, который взаимодействует с базами данных, и хотим, чтобы он поддерживал несколько баз данных. Мы могли бы это сделать в нашем Cargo.toml:

[features]
# ...
postgres = []
sqlite = []
tools = []

Возможность tools позволяет нам включить дополнительные инструменты, а возможности postgres и sqlite указывают, какие базы данных мы хотим поддерживать.

Раньше cargo build пыталась собрать все цели, которые вам нужны. Но что, если у нас есть файл src/bin/postgres-tool.rs, который является нужным только при условии, что возможности postgres и tools были включены? Раньше нам приходилось писать что-то вроде этого:

#[cfg(not(all(feature = "postgres", feature = "tools")))]
fn main() {
    println!("This tool requires the `postgres` and `tools` features to be enabled.");
}

#[cfg(all(feature = "postgres", feature = "tools"))]
fn main() {
    // код
}

Слишком много шаблонного кода для работы с cargo build. Еще печальнее дело обстояло с examples/, которые должны демонстрировать, как использовать вашу библиотеку. Но такие махинации возможны только при работе внутри самого пакета, поэтому вы потерпите неудачу, если попытаетесь использовать пример вне этого пакета.

С помощью нового ключа required-features мы можем добавить следующее:

[[bin]]
# ...
required-features = ["postgres", "tools"]

Теперь cargo build будет собирать наш postgres-tool, только если у нас включены две эти возможности, и поэтому мы можем написать нормальный fn main без всяких нагромождений вроде cfg.

Разработчики версии 1.17.0

Много людей внесли свой вклад в создание Rust 1.17. Мы не смогли бы сделать это без всех вас. Спасибо!

Авторы перевода и публикации @kgv, @vitvakatu, @ozkriff.

>>> Подробнее смотрите примечания к выпуску

★★★★★

Проверено: Shaman007 ()
Последнее исправление: sudopacman (всего исправлений: 3)
Ответ на: комментарий от pftBest

Ну раз нужны вставки кто же против. В любом случае ассемблер - прослойка между языком высокого уровня и железом.

microbash
()
Ответ на: комментарий от gene1

Я как то делал простые тесты скорости на Си. Три варианта: 1) функция, 2) инлайн функция, 3) макрос. 3-й вариант быстрее 1-го и 2-го. Потом я видел информацию, что в ядре линукса также для скорости используют макросы, хотя размер кода конечно увеличивается. Зачем вы предлагаете от них отказываться? Макросы - это уникальная вещь системного языка программирования. Причем в Rust макросы вроде бы гораздо более функциональны чем сишные.

microbash
()
Ответ на: комментарий от drfaust

80c51 и прочее старье не поддерживается компилятором llvm который используется в rust. поддержку AVR добавляют прямо сейчас, я думаю через месяц или два уже будет. MSP430 уже давно поддерживается, вот так выглядит обработчик прерывания для него:

#[no_mangle]
#[link_section = "__interrupt_vector_reset"]
pub static RESET_VECTOR: unsafe extern "msp430-interrupt" fn() = reset_handler;

unsafe extern "msp430-interrupt" fn reset_handler() {
    main();
}
pftBest ★★★★
()
Ответ на: комментарий от gene1

Макросы усложняют код

Наоборот, макросы делаются, чтобы упрощать код

могут иметь другой синтакс

Так для этого они и нужны — чтобы делать такие вещи, как https://usehelix.com и http://smallcultfollowing.com/babysteps/blog/2017/05/02/gnome-class-integrati...

увеличивают размер программы

С чего бы это? Размер бинарника остаётся таким же, как если весь boilerplate написать руками, а код проще и короче, и со специальным приспособленным для этой цели мини-синтаксисом.

Да, макросы — замена не большим функциям, а boilerplate-коду.

Макросы - вынужденное зло, которое используют в случаях, когда ничего лучше сделать нельзя.

Это в C, потому что там макросы кривые. В Lisp, например, макросы всем очень нравятся.

Но в Расте нужно использовать макрос, чтобы вывести «Hello World» в stdout. (!)

Не нужно:

io::stdout().write(b"hello world")?;

Есть макросы для удобного форматирования, да. Вместо printf-style шаблонов строк, которые парсятся в runtime и никак не проверяют соответствие шаблона и переданных данных, даже их количества.

В Rust вместо этого приятный мини-формат, похожий на питон. Оно всегда требует литерала в качестве формата, чтобы не дать сделать printf(user_supplied_string);, статически проверяет, что количество и типы аргументов соответствуют тому что нужно и генерит оптимизированный код для форматирования именно по этому шаблону.

И don't even get me started насчёт «удобности» форматирования с C++сным cout.

anonymous
()
Ответ на: комментарий от gene1

Вот и выросло поколение :)

Там возвращается ссылка на объект, который будет уничтожен при выходе из функции. Т.е. возвращается ссылка на мусор в памяти.

eao197 ★★★★★
()
Ответ на: комментарий от gene1

Шаблоны и макросы решают близкие задачи, Страуструп вроде как изначально даже не хотел добавлять шаблоны, предлагал обходиться препроцессором. Потом всё-таки решил, что шаблоны стоят того, чтоб их добавить. Дженерики в этом плане несколько урезанные шаблоны, решающие более узкий спектр задач. Проблема с C++ в том, что там нет нормальной кодогенерации, но есть богатые по возможностям шаблоны, которыми можно сделать многое, но результат получается нечитаемым. В расте решили дженерики оставить дженериками, а все более сложное передать макросам. Это разумно, см generic programming must go, даже гуру шаблонной магии Александреску эти шаблоны довели. Просьбы добавить вариадические дженерики естественны, вон, даже перегрузку функций предлагают добавить, просто потому что «наш раст не должен уступать замшелому цпп».

khrundel ★★★★
()
Ответ на: комментарий от Joe_Bishop

Это полнейшая, махровая пионерия

Так в чём проблема-то?

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Вместо printf-style шаблонов строк, которые парсятся в runtime и никак не проверяют соответствие шаблона и переданных данных, даже их количества.

Наглядная демонстрация уровня знаний растаманов.

anonymous
()
Ответ на: комментарий от microbash

3-й вариант быстрее 1-го и 2-го

Может, и код тех тестов есть? Все три варианта должны быть одинаковы по эффективности у нормального компилятора.

anonymous
()
Ответ на: комментарий от anonymous

Всё верно сказано. Костыли компиляторов к языку не относятся и работают как и положено костылям.

anonymous
()
Ответ на: комментарий от anonymous

Ты придумал новое гениальное расширение libastral-printf, которое не заглядывая в форматную строку знает количество аргументов, которое надо взять со стека вместе с их типами? И заодно проверяет, что на стеке лежат аргументы нужных типов в нужном количестве? Ты си хоть в книжке-то видел? И слова C calling conventions?

grossws
()
Ответ на: комментарий от microbash

такие тесты надо мерять после просмотра машинного кода, который сгенерировал компилятор. так что ерунда это и inline от макроса ничем не отличаются.

dzidzitop ★★
()
Ответ на: комментарий от anonymous

В Rust вместо этого приятный мини-формат, похожий на питон. Оно всегда требует литерала в качестве формата, чтобы не дать сделать printf(user_supplied_string);, статически проверяет, что количество и типы аргументов соответствуют тому что нужно и генерит оптимизированный код для форматирования именно по этому шаблону.

Плюсовые шаблоны с множественными типами делают это значительно проще, в том числе и без всяких форматов вообще и с возможностью передавать свои разные схемы форматирования для одного и того же типа. И без всяких cout. И с ленивыми вычислениями. Пользую, не могу нарадоваться.

https://github.com/dzidzitop/mirror/blob/master/src/mirror/utils.hpp#L248

Ну и если строка с плейсхолдерами понадобится, то и это есть. И без возможности передать «что-то не то».

А вариации на тему printf - это бред сивой кобылы. Разве что ограничить применение строкой-литералом (прощай, локализация) и проверкой компилятором соответствия. Это вообще нежизнеспособный кейс в любых многоязычных приложениях.

dzidzitop ★★
()
Последнее исправление: dzidzitop (всего исправлений: 5)
Ответ на: комментарий от dzidzitop

Оптимальный вариант формата строки для многоязычности

print(«foo {1} bar {2} baz {4} fuxx {3} lol {7}», var1, var2, var3, var4, var5, var6, var7, var8);

или

print(«foo {hello} bar {world} baz {tux} fuxx {buck} lol», params);

Без ограничений на то, откуда приходит строка формата и со строгой типизацией отображения параметров строки. Остальное - бред. Ну или я не знаю про лучший способ.

dzidzitop ★★
()
Ответ на: комментарий от pftBest

Можешь не ждать, они сказали что не собираются допиливать Servo, потому что это песочница для проверки новых идей а не конечный продукт.

Так и получается, что этот пресловутый rust не для промышленного применения, а полигон для академических умствований. Тоже нужно, но... как сказать, эта шумиха вокруг rust'а выглядит слегка раздутой.

anonymous
()
Ответ на: комментарий от khrundel

Stylo и Webrenderer из сервы в фирефокс переносят. На расте.

Будем посмотреть. Пока успехи более чем скромны: какая-то приблуда в лисе для mp4. От начала проекта прошло достаточно времени, и пора подводить наши неутешительные итоги.

anonymous
()
Ответ на: комментарий от khrundel

Stylo и Webrenderer из сервы в фирефокс переносят. На расте.

С учетом того, до какой степени Mozilla кастрировала C++ в своих гайдлайнах, пусть уж лучше делают это на Rust-е, чем на урезанном по самое не хочу C++98.

eao197 ★★★★★
()
Ответ на: комментарий от khrundel

От начала какого проекта? Квантум полгода как объявлен, обещают результаты в этом году.

Ладно кокетничать. Приведу пример. Когда был создан «C»? Сколько прошло от этого момента до появления в нем структур? Когда - да, черт подери! - на нем был переписан UNIX? Все это очень простые вопросы, а не эта маркетоидная чушь с пресловутым скоро (с)(R)(tm).

anonymous
()
Ответ на: комментарий от anonymous

Удивительно. Язык, созданный для переписывания юникса с ассемблера, сразу же использовали для переписывания юникса.

red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 1)
Ответ на: комментарий от mersinvald

А вот с этого места чуть поподробнее... А сколько человек в команде, есть ли тимлид, кто из местных регистрантов там состоит, чем, кроме пиара, занимается команда, как туда попасть?

shkolnick-kun ★★★★★
()
Ответ на: комментарий от dzidzitop

Оптимальный вариант формата строки для многоязычности

print(«foo {1} bar {2} baz {4} fuxx {3} lol {7}», var1, var2, var3, var4, var5, var6, var7, var8);

или

print(«foo {hello} bar {world} baz {tux} fuxx {buck} lol», params);

Ну оно как-то так и есть:

print!("foo {1} bar {2} baz {4} fuxx {3} lol {0}", var1, var2, var3, var4, var5);
print!("foo {hello} bar {world} baz {tux} fuxx {buck} lol", hello = 1, world = 2, tux = 3, buck = 4);
https://is.gd/Vth3bz

Но вообще для локализации нужны специальные билиотеки и фреймворки, там всё сильно сложнее, чем кажется.

Без ограничений на то, откуда приходит строка формата и со строгой типизацией отображения параметров строки.

Как раз для строгой типизации и нужны ограничения на строку формата.

anonymous
()
Ответ на: комментарий от shkolnick-kun

Решил развалить rust изнутри?

anonymous
()
Ответ на: комментарий от red75prim

Удивительно. Язык, созданный для переписывания юникса с ассемблера, сразу же использовали для переписывания юникса.

Какой ты умничка!)) Правда непонятно зачем и к чему ты это накорябал. Анальное недержание в мозгу? Вправду, к чему твой высер?

anonymous
()
Ответ на: комментарий от khrundel

Что-то мне подсказывает, что тот юникс был в разы проще современного браузера.

Не кокетничай. О браузере речь уже не идет. Хотя бы что-нибудь работающее, посложнее «Привет, мир!». И хотелось бы в исторически обозримые сроки.

anonymous
()
Ответ на: комментарий от khrundel

На порядок. Где-то публиковались исходники раннего юникс - там си был просто как макроассемблер, сейчас так даже первокуры не пишут.

anonymous
()
Ответ на: комментарий от anonymous

Когда - да, черт подери! - на нем был переписан UNIX?

Так одно дело переписать небольшой существующий проект на другом языке без больших изменений, другое дело — написать принципиально новый движок с принципиально новй архитектурой, который будет на порядки быстрее всего существующего, и встроить его в существующий браузер, так чтобы многочисленные пользователи ничего не заметили.

It’s like figuring out how to replace a jet engine on a jet that’s still flying.

anonymous
()
Ответ на: комментарий от anonymous

написать принципиально новый движок с принципиально новй архитектурой, который будет на порядки быстрее всего существующего, и встроить его в существующий браузер, так чтобы многочисленные пользователи ничего не заметили.

Кто против-то? Я тоже за то, чтобы все хорошее победило все плохое. Поставило на колени. И зверски убило.

Продукт этот где? Прототип продукта? Хоть что-то работающее. Разработчики «C» за подобное время, потраченное на rust, создали уйму полезного.

anonymous
()
Ответ на: комментарий от anonymous

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

Да, с локализацией сложнее. Но с printf с литералами формата там точно делать нечего. А этот растовый print! поддерживает передачу динамической строки формата? И что происходит внутри print! для того, чтобы напечатать значение параметра? Я могу туда передать float, так, чтобы напечаталось 0.2323 для значения 0.23232232332?

dzidzitop ★★
()
Последнее исправление: dzidzitop (всего исправлений: 2)
Ответ на: комментарий от shkolnick-kun

Всё просто, основная площадка: gitter, сообщество ruRust. 137 участников, активно постоянно человек 20.
В основном занимаемся поддержкой новичков и друг друга по теме топика. Переводим статьи, иногда пишем и публикуем свои, всё по мере сил и желания. Лид и роадмары есть)

mersinvald ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Разработчики «C» за подобное время, потраченное на rust, создали уйму полезного

Огласите весь список! Что там полезного создали в первой половине 70-х?

anonymous
()
Ответ на: комментарий от anonymous

Продукт этот где? Прототип продукта? Хоть что-то работающее. Разработчики «C» за подобное время, потраченное на rust, создали уйму полезного.

https://servo.org/

https://air.mozilla.org/bay-area-rust-meetup-february-2016/

Это что касается Servo/Quantum/Firefox. Вообще на Rust уже много чего написано, в том числе куски бекэнда у Dropbox, Coursera, и даже у всеми любимых Canonical и NPM.

Поиск в Visual Studio Code написан на Rust (ripgrep).

Ну и GNOME движется в эту сторону, librsvg уже переписывают.

anonymous
()
Ответ на: комментарий от anonymous

Огласите весь список! Что там полезного создали в первой половине 70-х?

Алло, ты обезумел в своем манямирке? Головушка совсем не того?

anonymous
()
Ответ на: комментарий от anonymous

куски бекэнда у Dropbox, Coursera, и даже у всеми любимых Canonical и NPM
Поиск в Visual Studio Code написан на Rust (ripgrep).
Ну и GNOME движется в эту сторону, librsvg уже переписывают.

Целиком работающего продукта пока нет. Неудивительно. Ну и ладно, еще лет 7 подождем.

anonymous
()
Ответ на: комментарий от anonymous

Так вроде Quantum уже в этом году обещают.

«Пока не вложу перста».(C) Как будет, так и поговорим.

anonymous
()
Ответ на: комментарий от khrundel

Компилятор раста. Серво. Карго.

Я слышал эти слова. Но все познается в сравнении. Пока не будет компилятора «C» для сравнения все это будет: бла-бла-бла

anonymous
()
Ответ на: комментарий от anonymous

Пока не будет компилятора «C» для сравнения

Компилятора С версии 1972-го года? Месяца за два-три набросать можно. Но зачем.

red75prim ★★★
()
Ответ на: комментарий от anonymous

Т. е. уже нужен не просто сложный работающий проект, а конкретный и с перламутровыми пуговицами? Ну-ну.

khrundel ★★★★
()
Ответ на: комментарий от red75prim

Месяца за два-три набросать можно

Имхо, за неделю-две, но придется еще поискать спеки на язык (а они не факт что есть).

anonymous
()
Ответ на: комментарий от anonymous

Имхо, за неделю-две,

Там же «готовый продукт» нужен, а это ещё и ld, ar, может и ещё что-то.

red75prim ★★★
()
Ответ на: комментарий от bernd

увидел это и отпало желание открывать сайт с рустом

А прочитать к чему был пример этого кода видать не судьба.
«смотрю в книгу - вижу фигу»

WatchCat ★★★★★
()
Ответ на: комментарий от dzidzitop

Это не то. В самом print! можно это сделать без создания промежуточной никому не нужной строки?

У print!, println!, write!, writeln!, format! одинаковый синаксис и общая реализация внутри, все они могут в сложное форматирование с выравниванием и знаками после запятой. И эта реализация выводит байты в любой поток — объект, реализующий трейт std::io::Write. Можно в raw stdout. Можно с буферизацией. Можно в сокет. Можно в строку на куче, динамически её расширяя.

Если нужна промежуточная строка — это делается явно: вывести всё в строку на куче (format!) и потом напечатать её. Если так не делать, ничего лишнего не создаётся. Zero-cost abstractions.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.