Println! error: ожидается, что аргумент literal / format должен быть строковым литералом

Эта чрезвычайно простая программа Rust:

fn main() { let c = "hello"; println!(c); } 

выдает следующую ошибку времени компиляции:

 error: expected a literal --> src/main.rs:3:14 | 3 | println!(c); | ^ 

В предыдущих версиях Rust ошибка:

 error: format argument must be a string literal. println!(c); ^ 

Замена программы:

 fn main() { println!("Hello"); } 

Работает отлично.

Смысл этой ошибки не ясен для меня, и поиск Google не проливает свет на него. Почему передача c в println! макрос вызывает ошибку времени компиляции? Это кажется довольно необычным поведением.

TL; DR Если вам все равно, почему и просто хотите исправить это, обратитесь к ответу на сестры .


Причина, по которой

 fn main() { let c = "hello"; println!(c); } 

Не получается, потому что println! макрос просматривает строку во время компиляции и проверяет соответствие аргументов и аргументов по количеству и типу (это очень хорошо!). На данный момент во время макрооценки невозможно сказать, что c произошло из литерала или функции или что у вас есть.

Вот пример того, что макрос расширяет:

 let c = "hello"; match (&c,) { (__arg0,) => { #[inline] #[allow(dead_code)] static __STATIC_FMTSTR: &'static [&'static str] = &[""]; ::std::io::stdio::println_args(&::std::fmt::Arguments::new( __STATIC_FMTSTR, &[::std::fmt::argument(::std::fmt::Show::fmt, __arg0)] )) } }; 

Я не думаю, что для компилятора это вообще невозможно понять, но это, вероятно, потребует большой работы (потенциально для небольшого выигрыша). Макросы работают на участках АСТ, которые, как я предполагаю, имеют только информацию о типе. Чтобы работать в этом случае, AST должен будет указать источник идентификатора и достаточную информацию, чтобы определить, что он «безопасен». Кроме того, он может плохо взаимодействовать с типом вывода – вы бы хотели знать тип до его выбора!

Сообщение об ошибке запрашивает «строковый литерал». Есть вопрос о том, что это значит, что связано с входом в Википедию :

литерал – это обозначение для представления фиксированного значения в исходном коде

"foo" – строковый литерал, 8 – числовой литерал. let s = "foo" – это оператор, который присваивает значение строкового литерала идентификатору (переменной). println!(s) – это оператор, который предоставляет идентификатор макроса.

Это должно работать:

 fn main() { let c = "hello"; println!("{}", c); } 

Строка "{}" является шаблоном, где {} будет заменен следующим аргументом, переданным println! ,

Если вы действительно хотите определить первый аргумент println! в одном месте я нашел способ сделать это. Вы можете использовать макрос:

 macro_rules! hello {() => ("hello")}; println!(hello!()); 

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

 macro_rules! cell_format {() => ("{:<10}")}; // Pads with spaces on right // to fill up 10 characters println!(cell_format!(), "Foo"); println!(cell_format!(), 456); 

Макрос спас меня от необходимости дублировать опцию форматирования в моем коде.

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

Если ваша строка формата будет повторно использоваться только умеренное количество раз, и только некоторые переменные данные будут изменены, то небольшая функция может быть лучшим вариантом, чем макрос:

 fn pr(x: &str) { println!("Some stuff that will always repeat, something variable: {}", x); } pr("I am the variable data"); 

Выходы

Некоторые вещи, которые всегда будут повторяться, что-то переменное: я переменные данные

  • Каков де-факто способ чтения и записи файлов в Rust 1.x?
  • Могу ли я написать Итератор, который сам мутирует, а затем дает ссылку на себя?
  • Ржавый заимствование HashMap длится за пределами его объема?
  • Почему мой пользователь не вводит корректное соответствие stdin?
  • В чем разница между размещением «mut» перед именем переменной и после «:»?
  • Печатает! заимствовать или владеть переменной?
  • Как передать непересекающиеся fragmentы из вектора в разные streamи?
  • Как получить изменяемые ссылки на два элемента массива одновременно?
  • Можно ли управлять размером массива с помощью параметра типа общего?
  • Есть ли способ объединить несколько признаков, чтобы определить новый признак?
  • Как преобразовать String в & 'static str
  • Interesting Posts

    Как сохранять cookie при использовании HTTPUrlConnection?

    Какое программное обеспечение для удаленного рабочего стола требует минимальной конфигурации на стороне клиента?

    Сопоставление ключа с чем-то, что не на клавиатуре

    получить высоту и ширину макета во время работы андроида

    Использование анонимных пространств имен в файлах заголовков

    Почему для местоположения игровых сервисов необходимы разрешения android.permission.WRITE_EXTERNAL_STORAGE и android.permission.READ_EXTERNAL_STORAGE?

    Расширение Google Chrome для синхронизации расширений

    Почему Windows 10 показывает «Возобновить с гибернации» при каждой загрузке, хотя она была отключена правильно?

    Внутренний class может получить доступ, но не обновлять значения – AsyncTask

    Напишите метод режима в Java, чтобы найти наиболее часто встречающийся элемент в массиве

    Переместить конструктор для std :: mutex

    C # Image.Clone Out of Memory Exception

    Как выбрать одно поле в MongoDB?

    Как развернуть мой собственный компьютер в качестве веб-сервера?

    увеличить высоту div с его содержимым

    Давайте будем гением компьютера.