这是一个微不足道的 Rust 自行车脱落问题,但我一直看到它以次优(冗长)的方式实现,我想知道 stdlib 是否应该有所帮助,或者是否有一个好的模式?
目标:
假设的理想代码——是否值得从 Rust stdlib 请求它或至少将其添加到 itertools(参见问题)?
fn print_functional(items: &[&str]) {
items.foreach_with_separator(
|elem| {
// some arbitrary complex item handling, not printing
print!("{elem}");
},
|| {
// some arbitrary complex "separator" handling
print!(", "),
}
);
}
Run Code Online (Sandbox Code Playgroud)
我主要看到这两种方法。由于格式化代码重复或冗长的上下文状态保留,它们不太理想。我的目标是仅使用 stdlib 来完成此操作,而不创建任何复杂的辅助函数。
fn main() {
let items = vec!["foo", "bar", "baz"];
print_with_var(&items);
print_split_last(&items);
}
fn print_with_var(items: &[&str]) {
let mut first_printed = false;
for elem in elems {
if first_printed {
print!(", ");
} else {
first_printed = true;
}
// this represents some multi-line processing,
// but for this example I'm keeping it simple
let formatted_value = elem.to_string();
print!("{formatted_value}");
}
}
fn print_split_last(items: &[&str]) {
if let Some((last, elems)) = items.split_last() {
for elem in elems {
// this is sub-optimal because elem formatting is duplicated
let formatted_value = elem.to_string();
print!("{formatted_value}, ");
}
let formatted_value = last.to_string();
print!("{formatted_value}");
}
}
Run Code Online (Sandbox Code Playgroud)
您不需要布尔标志。您可以使用底层迭代器,然后在获取第一个元素后将其余元素传递给循环for(或者.map更实用的样式):
pub fn foo(ls: &[&str]) -> Option<()> {
// We get an iterator over the items in a slice
let mut iter = ls.iter();
// Get the first item. Note that it's
// an Option, the slice may be empty.
// If it is this will essentially
// return early
let first = iter.next()?;
// Do something special with the first element
println!("first: {first}");
// Loop over the rest
for item in iter {
println!("item: {item}");
}
// Return an empty option to satisfy the
// return type
Some(())
}
fn main() {
foo(&vec!["a", "b", "c"]);
}
Run Code Online (Sandbox Code Playgroud)
你可以在操场上看到,没有解释性的注释,它非常简洁。