如何实现 Lispian cond 宏?
How to implement the Lispian cond macro?
预期用途:
cond! {
x > 5 => 0,
x < 3 => 1,
true => -1
}
应扩展为:
if x > 5 { 0 } else if x < 3 { 1 } else if true { -1 }
请注意,它不会生成包罗万象的 else { ... }
后缀。
我的尝试:
macro_rules! cond(
($pred:expr => $body:expr) => {{
if $pred {$body}
}};
($pred:expr => $body:expr, $($preds:expr => $bodies:expr),+) => {{
cond! { $pred => $body } else cond! { $($preds => $bodies),+ }
}};
);
但是,编译器抱怨 else
关键字。
error: expected expression, found keyword `else`
--> src/main.rs:32:34
|
32 | cond! { $pred => $body } else cond! { $($preds => $bodies),+ }
| ^^^^
Rust 中的宏不像 C 预处理器那样执行文本替换。此外,宏的结果已经是 "parsed",因此您不能仅在宏调用之后附加一些本应是宏扩展到的部分的内容。
在你的例子中,你不能在第一个 cond!
调用之后放置一个 else
,因为编译器已经完成了对 if
表达式的解析;您需要将 if
和 else
放在一起。同样,当您在 else
之后再次调用 cond!
时,您需要在调用周围添加大括号,因为序列 else if
不会开始嵌套的 if
表达式。
macro_rules! cond {
($pred:expr => $body:expr) => {
if $pred { $body }
};
($pred:expr => $body:expr, $($preds:expr => $bodies:expr),+) => {
if $pred { $body } else { cond! { $($preds => $bodies),+ } }
};
}
但最终,这个宏几乎没有用。没有 else
子句的 if
表达式总是将其类型推断为 ()
,因此除非所有分支都计算为 ()
(或发散),否则展开的宏将产生类型不匹配错误。
预期用途:
cond! {
x > 5 => 0,
x < 3 => 1,
true => -1
}
应扩展为:
if x > 5 { 0 } else if x < 3 { 1 } else if true { -1 }
请注意,它不会生成包罗万象的 else { ... }
后缀。
我的尝试:
macro_rules! cond(
($pred:expr => $body:expr) => {{
if $pred {$body}
}};
($pred:expr => $body:expr, $($preds:expr => $bodies:expr),+) => {{
cond! { $pred => $body } else cond! { $($preds => $bodies),+ }
}};
);
但是,编译器抱怨 else
关键字。
error: expected expression, found keyword `else`
--> src/main.rs:32:34
|
32 | cond! { $pred => $body } else cond! { $($preds => $bodies),+ }
| ^^^^
Rust 中的宏不像 C 预处理器那样执行文本替换。此外,宏的结果已经是 "parsed",因此您不能仅在宏调用之后附加一些本应是宏扩展到的部分的内容。
在你的例子中,你不能在第一个 cond!
调用之后放置一个 else
,因为编译器已经完成了对 if
表达式的解析;您需要将 if
和 else
放在一起。同样,当您在 else
之后再次调用 cond!
时,您需要在调用周围添加大括号,因为序列 else if
不会开始嵌套的 if
表达式。
macro_rules! cond {
($pred:expr => $body:expr) => {
if $pred { $body }
};
($pred:expr => $body:expr, $($preds:expr => $bodies:expr),+) => {
if $pred { $body } else { cond! { $($preds => $bodies),+ } }
};
}
但最终,这个宏几乎没有用。没有 else
子句的 if
表达式总是将其类型推断为 ()
,因此除非所有分支都计算为 ()
(或发散),否则展开的宏将产生类型不匹配错误。