26

I'm trying to concatenate static strings and string literals to build another static string. The following is the best I could come up with, but it doesn't work:

const DESCRIPTION: &'static str = "my program";
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const VERSION_STRING: &'static str = concat!(DESCRIPTION, " v", VERSION);

Is there any way to do that in Rust or do I have to write the same literal over and over again?

CodeMonkey
  • 614
  • 6
  • 15
  • Take a look at `lazy_static`: https://github.com/rust-lang-nursery/lazy-static.rs – starblue Feb 02 '16 at 16:08
  • @starblue Quoting from the README: "Using this macro, it is possible to have statics that require code to be executed at runtime in order to be initialized." In my example, no code should have to be executed at runtime. – CodeMonkey Feb 02 '16 at 16:13

3 Answers3

18

Since I was essentially trying to emulate C macros, I tried to solve the problem with Rust macros and succeeded:

macro_rules! description {
    () => ( "my program" )
}
macro_rules! version {
    () => ( env!("CARGO_PKG_VERSION") )
}
macro_rules! version_string {
    () => ( concat!(description!(), " v", version!()) )
}

It feels a bit ugly to use macros instead of constants, but it works as expected.

CodeMonkey
  • 614
  • 6
  • 15
12

The compiler error is

error: expected a literal

A literal is anything you type directly like "hello" or 5. The moment you start working with constants, you are not using literals anymore, but identifiers. So right now the best you can do is

const VERSION_STRING: &'static str =
    concat!("my program v", env!("CARGO_PKG_VERSION"));

Since the env! macro expands to a literal, you can use it inside concat!.

oli_obk
  • 25,579
  • 3
  • 73
  • 89
  • 4
    So, as I feared, I'll have to write the same literal over and over again. – CodeMonkey Feb 02 '16 at 16:05
  • 1
    You can always try to improve the `concat` macro to support constants ;) But it'll take a month or so until it's in stable rust – oli_obk Feb 02 '16 at 16:34
  • `concat` seems to be a compiler built-in: https://github.com/rust-lang/rust/blob/master/src/libstd/macros.rs#L311 I really don't want to patch the compiler ;) – CodeMonkey Feb 02 '16 at 16:48
  • You can still put up an issue in the issue tracker. It shouldn't be too much of a problem to allow simple constants in `concat!` – oli_obk Feb 03 '16 at 08:12
  • It will be a problem, since macros by definition can't know the value of constants (even the built-in ones), they run before the constants are evaluated and operate only on tokens. – Cerberus Feb 11 '22 at 09:38
2

Another method is the const_concat! macros.

#[macro_use]
extern crate const_concat;

const GREETING: &str = "Hello";
const PLACE: &str = "world";
const HELLO_WORLD: &str = const_concat!(GREETING, ", ", PLACE, "!");

assert_eq!(HELLO_WORLD, "Hello, world!");
xamgore
  • 616
  • 9
  • 20