问题
So I have this:
struct User {
reference: String,
email: String,
firstname: String,
lastname: String
}
fn main() {
let user = User {
reference: "ref".to_string(),
email: "em@ail.com".to_string(),
firstname: "John".to_string(),
lastname: "Doe".to_string()
};
concat!(&user.firstname.as_string(), " ", &user.lastname.as_string());
}
that's returning an error:
error: expected a literal
concat!(&user.firstname.as_string(), " ", &user.lastname.as_string());
^~~~~~~~~~~~~~~~~~~~~~~~~~
But I thought that .as_string()
already makes it a literal, does it not? I am also finding as_slice()
and as_str()
references all over the place and it's confusing. Which one is it?
UPDATE OK, I was hoping I don't have to paste the whole thing here, but I guess I just have to do that anyway:
extern crate postgres;
use postgres::{Connection, SslMode};
struct User {
reference: String,
email: String,
firstname: String,
lastname: String
}
fn main() {
let conn = Connection::connect("postgres://postgres:postgres@localhost/mydb", &SslMode::None).unwrap();
let user = User {
reference: "ref".to_string(),
email: "em@ail.com".to_string(),
firstname: "John".to_string(),
lastname: "Doe".to_string()
};
let query = "INSERT INTO foo (user_id, name) VALUES ((SELECT id FROM user WHERE email = $1), $2)";
conn.execute(query, &[&user.email, concat!(&user.firstname.as_slice(), " ", &user.lastname.as_slice())]).unwrap();
}
回答1:
There are misunderstandings here.
concat!
is a macro, that is a "code-generation" mechanism; as a result it is expanded at the first stages of the compilation, before type resolution/ownership checks/etc...
A literal is a value written as-is in the code: true
, 1
, "hello"
; the result of an expression cannot be a literal (by definition). The resulting types may look similar (or even be identical) but types are irrelevant here.
So, what do you really want? I guess you just want to concatenate strings. For String
, you can just use +
:
let fullname = user.firstname + " " + user.lastname;
conn.execute(query, &[&user.email, &fullname]).unwrap();
Alternatively, if you need some more complex formatting, you can use the format!
macro (which does not require literals), here it would be:
let fullname = format!("{} {}", user.firstname, user.lastname);
回答2:
Rust concat!
expects a literal as in a symbol literal (like true
, 32
'c'
, "string"
) since it works in earliest parts of compile stages. During that time runtime value of types aren't resolved yet.
Based on your postgress example it seems like the best course of action is to simply create a function that returns full name or whatever you need:
struct User {
... //same
}
impl User {
fn get_fullname(&self) -> String
{
let mut fullname = String::new();
fullname.push_str(&self.firstname);
fullname.push_str(" ");
fullname.push_str(&self.lastname);
fullname
}
}
fn main() {
let user = User {
reference: "ref".to_string(),
email: "em@ail.com".to_string(),
firstname: "John".to_string(),
lastname: "Doe".to_string()
};
let x = &[&user.email, &user.get_fullname()];
conn.execute(query, &[x]);
I propose this, because it seems getting fullname is something you'll want to use often on your structs. However if not, you could format the values as Matthiueu M. suggested and just concatenate them assuming this is a one-time thing.
(Playground)
来源:https://stackoverflow.com/questions/30480406/string-concat-error-expected-a-literal