Is it possible to use a variable as the fill argument in the format! macro?

大城市里の小女人 提交于 2020-07-03 08:24:20

问题


I wanted to imitate Python's rjust, ljust, and center functions using the format! macro, but I was only able to work out a solution where you can pass in the string and the width. If you want to pass in the fill-argument it doesn't work.

The documentation tells me that it is possible to provide variables to format! and for the width argument it works just fine. When I try to use a variable for fill, the compiler does not recognize the pattern.

Just the width as a variable works:

fn rjust(text: &str, width: usize, fill: Option<char>) -> String {
    format!("{text:>width$}", text = text, width = width)
}
println!("{}", rjust("Hello", 10)); // "     Hello"

Providing the fill as a variable does not work:

fn rjust(text: &str, width: usize, fill: char) -> String {
    format!(
        "{text:fill>width$}",
        text = text,
        fill = fill,
        width = width
    )
}
println!("{}", rjust("Hello", 20, '*'));

The error message:

error: invalid format string: expected `'}'`, found `'>'`
 --> src/lib.rs:4:24
  |
4 |             "{text:fill>width$}",
  |              -         ^ expected `}` in format string
  |              |
  |              because of this opening brace
  |
  = note: if you intended to print `{`, you can escape it using `{{`

If I provide a single character instead of the fill-variable, it works fine. Notice the * character:

fn rjust(text: &str, width: usize, fill: char) -> String {
    format!("{text:*>width$}", text = text, width = width)
}
println!("{}", rjust("Hello", 20, '_')); // ***************Hello

I expected the fill-variable version to work the same as the hardcoded * character version.

A workaround is to subtract the length of the text from the width and then create a String of that length (fill-length) made of fill-characters and concatenate them:

fn rjust(text: &str, width: usize, fill: char) -> String {
    let fill_len = width - text.len();
    let fill_str: String = (0..fill_len).map(|_| fill).collect();
    String::from(fill_str + text)
}
println!("{}", rjust("Hello", 20, '*')); // ***************Hello

回答1:


Unfortunately there is no built-in way to do this.

The formatting syntax evolved with features that early Rust adopters needed at the time. Its terseness means that new features are very difficult to add after the fact.



来源:https://stackoverflow.com/questions/56666258/is-it-possible-to-use-a-variable-as-the-fill-argument-in-the-format-macro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!