Ошибка в Rust: "expected a literal" при использовании println! — как исправить?
Почему возникает ошибка?
В Rust макрос println! — это не функция, а макрос, который работает на уровне синтаксического анализа. Он ожидает строковый литерал (строку в кавычках, известную на этапе компиляции) в качестве первого аргумента. Конкатенация строк через + внутри макроса не поддерживается, потому что макрос разбирает аргументы статически, а не во время выполнения.
Правильный синтаксис: плейсхолдеры
Вместо конкатенации используйте фигурные скобки {} как плейсхолдеры для значений. Вот как исправить ваш пример:
fn main() {
let name = "Alice";
println!("Hello, {}!", name); // Выведет: Hello, Alice!
}
Фигурные скобки — это место, куда подставится значение переменной. Вы можете использовать несколько плейсхолдеров:
let x = 10;
let y = 20;
println!("x = {}, y = {}", x, y); // x = 10, y = 20
Форматирование с индексами и именами
Если у вас много аргументов, можно указывать индексы:
println!("{1} is {0} years old", 25, "Bob"); // Bob is 25 years old
Или именованные параметры (только в Rust 1.58+):
println!("{name} is {age} years old", name = "Alice", age = 30);
Почему нельзя просто "склеивать"?
В отличие от динамических языков, Rust — статически типизированный. Макрос println! на этапе компиляции проверяет количество и типы аргументов. Конкатенация строк — это операция времени выполнения, которая не вписывается в эту модель. Если вам нужно собрать сложную строку, используйте format!:
let greeting = format!("Hello, {}!", name);
println!("{}", greeting); // Тоже работает
Типичные ошибки начинающих
- Забыли кавычки у литерала:
println!("{}", name)— правильно,println!({}, name)— ошибка. - Пытаетесь использовать println! как обычную функцию: Не пишите
println!("строка" + var). - Выводите саму переменную без плейсхолдера:
println!(name)— не скомпилируется, так как макрос ждёт литерал.
Надеюсь, теперь стало понятнее! Rust требует строгого синтаксиса, но зато вы получаете гарантии безопасности и производительности на этапе компиляции.
<<Альтернатива: использование макроса write! или форматирование через Display
Если вам нужно вывести данные не только в консоль, но и, например, в строку, используйте format! — он работает так же, как println!, но возвращает String:
let result = format!("Привет, {}! Сегодня {} число.", "Мир", 15);
println!("{}", result); // Привет, Мир! Сегодня 15 число.
Для вывода в поток (файл, сокет) используйте макрос write!:
use std::io::Write;
fn main() {
let mut output = Vec::new();
write!(&mut output, "Значение: {}", 42).unwrap();
println!("{:?}", output); // Выведет байты строки "Значение: 42"
}
Что если нужно вывести тип, не реализующий Display?
Некоторые типы (например, срезы или кортежи) не поддерживают плейсхолдер {}. Используйте {:?} для отладки (требуется трейт Debug):
let numbers = vec![1, 2, 3];
println!("{:?}", numbers); // [1, 2, 3]
Или {:#?} для красивого форматирования с отступами. Это удобно при отладке сложных структур.
Ответов пока нет.
Войдите чтобы оставить ответ