If you use format! to produce a string from objects, e.g., consts, that are known at compile time, I would think that most -- or all -- of the work happens at compile time. Am I correct?
Thanks --
If you use format! to produce a string from objects, e.g., consts, that are known at compile time, I would think that most -- or all -- of the work happens at compile time. Am I correct?
Thanks --
I don’t think so - it calls into the formatting machinery at runtime.
That's too bad.
Do you know of a way to concatenate strings at compile time, some perhaps defined as consts? I'm looking for something analogous to C's useful feature that "foo""bar" = "foobar". Combined with #defines this can be helpful in, for example, building queries with compile-time parameters:
#define LIMIT "10"
char *query = "select * from xyz limit "LIMIT;
I'm guessing there's a way to do this with Rust macros, but the macro facility is complex and, at least for me, under-documented. I can achieve the effect I want with m4 and a little makefile trickery, but I'd like to know if there's a way to do this sort of thing in Rust alone.
I'm not sure if there's a non-macro way to do it - it would require const_fn to allow this level of compile-time eval.
A hacky/quick way to do this (with a simple macro) is:
macro_rules! limit {
() => {"10"};
}
const QUERY: &'static str = concat!("select * from xyz limit ", limit!());
Thanks. My only issue with that solution is the readability of the code vs using m4, where the query would look like:
define(LIMIT, 10)dnl
const QUERY: &'static str = "select * from xyz limit LIMIT";
The readability issue becomes more of a problem with actual and much more complex queries.
I'd probably just do:
macro_rules! limit_sql {
($sql:tt, $v:expr) => {concat!($sql, " limit ", $v)};
}
const QUERY: &'static str = limit_sql!("select * from xyz", 10);
This is super straightforward (IMO). You can probably get fancier with more sophisticated macros, but I know you're trying to avoid that.
I don't know if you're using a sql query as just an example or not, but if constructing and running sql queries is your actual use case, have you looked at the diesel crate? Here's a good video by its creator showcasing how they're able to strip away a lot of the abstraction during sql generation (spoiler: it's not a compile time constant at the end
): RustConf 2017 - Type System Tips for the Real World by Sean Griffin - YouTube
Thanks again. Yes, that's a nice solution, but I still prefer using m4, because complicated queries are more readable, due to the ability to embed the variables to be replaced directly in the string.
But I will keep this in mind, because this technique can be useful in other situations where readability is less of an issue.