如何创建Rust的<tr><td>宏?解决多列表格生成语法报错问题
问题
我有不少不同列数的数据集要插入表格,觉得Yew框架太冗余,想按KISS原则简化操作。原本用这种方式生成表格行:
// format!("<tr><td>{e1}</td><td>{e2}</td></tr>") – 不行,参数可能是表达式 format!("<tr><td>{}</td><td>{}</td></tr>", e1, e2)
我想改成支持任意列数的宏,试了这段代码:
macro_rules! tr { ($($td:expr),*) => { format!(concat!("<tr>", $("<td>{}</td>"),* "</tr>"), $($td),*) } } tr!(e1, e2)
结果报错:attempted to repeat an expression containing no syntax variables matched as repeating at this depth
于是我改成这样:
macro_rules! tr { ($($td:expr),*) => { format!(concat!("<tr>", $({ $td; "<td>{}</td>" }),* "</tr>"), $($td),*) } }
又报错:expected token: ,
正确的语法应该怎么写?
解决方案
问题出在宏里concat!的重复语法不符合Rust宏规则:第一个错误是因为重复块$("<td>{}</td>"),*里没有引用宏捕获的重复变量$td,Rust宏要求重复块必须包含对应的重复捕获项;第二个错误是用了${ ... }这种无效的宏语法。
正确的写法如下,同时支持末尾可选逗号(更易用):
macro_rules! tr { ($($td:expr),* $(,)?) => { format!( concat!("<tr>", $( "<td>{}</td>" ),* "</tr>"), $($td),* ) }; }
说明
concat!("<tr>", $( "<td>{}</td>" ),* "</tr>")会根据传入的参数数量,自动生成对应个数的<td>{}</td>片段,拼接成完整的HTML模板字符串。$(,)?)允许宏接受末尾带逗号的参数(比如tr!(a, b,)),使用起来更灵活。
测试示例:
fn main() { let col1 = "姓名"; let col2 = "年龄"; let col3 = "城市"; println!("{}", tr!(col1, col2)); // 输出: <tr><td>姓名</td><td>年龄</td></tr> println!("{}", tr!(col1, col2, col3)); // 输出: <tr><td>姓名</td><td>年龄</td><td>城市</td></tr> }
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

