英文:
Rust preprocessor: Plain text replacement like #define for syntax simplification
问题
在Rust中,您可以使用宏(macros)来实现与C中#define
类似的纯文本替换。以下是示例宏定义,用于实现您描述的功能:
macro_rules! unwrap_or_default {
($expr:expr) => {
$expr.unwrap_or_default()
};
}
macro_rules! option_type {
($t:ty) => {
Option<$t>
};
}
然后,您可以在代码中使用这些宏来进行替换,如下所示:
struct ReturnPath {
name: unwrap_or_default!(String),
file_type: unwrap_or_default!(String),
mtime: unwrap_or_default!(i64),
}
这将使您的代码更简洁,类似于您在问题中描述的所需效果。希望这可以帮助您实现您的目标。
英文:
In C, you can define macros using #define
to have something globally replaced by the C preprocessor. How can I achieve the same plain-text replacement in rust?
My goal is to define macros that simplifies Rust syntax and reduce boilerplate, such as replacing !!.
with .unwrap().
to simulate the "non-null assertion operator" syntax in Kotlin, Swift, or TypeScript, and replacing (\w+)\?\?
with Option<$1>
to simplify optional type syntax.
For example, the following struct
struct ReturnPath {
name: Option<String>,
file_type: Option<String>,
mtime: Option<i64>
}
would be much shorter in the processed syntax:
struct ReturnPath {
name: String??,
file_type: String??,
mtime: i64??
}
答案1
得分: 1
How can I achieve the same plain-text replacement in rust?
如何在Rust中实现相同的纯文本替换?
You can't do this without a DSL macro, essentially.
基本上,你不能在没有DSL宏的情况下实现这个。
C macros are token-replacement and happen before the syntax-checking step -- Rust macros are more akin to Lisp macros, which happen during the parsing step. See: https://softwareengineering.stackexchange.com/a/28387
C宏是令牌替换,发生在语法检查步骤之前 - Rust宏更类似于Lisp宏,在解析步骤期间发生。参见:https://softwareengineering.stackexchange.com/a/28387
replacing (\w+)?? with Option<$1> to simplify optional type syntax.
将 (\w+)?? 替换为 Option<$1> 以简化可选类型语法也不会在更复杂的情况下实现你想要的效果,比如如果你有Result<T, R>??
或Vec<&'static str>??
等情况。这是因为Rust的语法比正则表达式更强大 - 它在很大程度上是上下文无关的,但也有一些上下文敏感的部分(链接:https://stackoverflow.com/questions/43677722/is-rusts-syntactical-grammar-context-free-or-context-sensitive#:~:text=Answer%20straight%20from%20the%20source%20code%20for%20Rust%3A,string%20literals%20are%20the%20source%20of%20the%20problem.)。
What you're probably looking for is some sort of declarative and syntactical replacement from ($t:ty) \? \? => Option<$t>
.
你可能正在寻找的是一种从 ($t:ty) \? \? => Option<$t>
进行声明性和语法替换的方式。
In addition, this regex can also probably match on non-types like a??
if a: Option<Option<T>>
.
此外,如果 a: Option<Option<T>>
,这个正则表达式可能也能匹配非类型的内容,比如 a??
。
If you wanted to create a special syntax for this, you'd probably do something like:
如果你想要为此创建特殊的语法,你可能会这样做:
macro_rules! shorthand_struct_fields {
/* rows of idents to types and then adjust struct definition but with T?? substituted for Option<T> */
}
struct Foo {
shorthand_struct_fields! {
x: i32??,
}
}
I'm not sure if this is such a good idea, but if you do want to create this large macro, you would be best suited by writing a declarative macros with sub-macros that use @
rules, like so: http://danielkeep.github.io/tlborm/book/pat-internal-rules.html
我不确定这是否是一个好主意,但如果你确实想创建这个大型宏,最好的方法是编写一个使用 @
规则的声明性宏,其中包含子宏,就像这样:http://danielkeep.github.io/tlborm/book/pat-internal-rules.html
英文:
> How can I achieve the same plain-text replacement in rust?
You can't do this without a DSL macro, essentially.
C macros are token-replacement and happen before the syntax-checking step -- Rust macros are more akin to Lisp macros, which happen during the parsing step. See: https://softwareengineering.stackexchange.com/a/28387
> replacing (\w+)?? with Option<$1> to simplify optional type syntax.
This also won't do what you want it to do in more complicated scenarios, such as if you have Result<T, R>??
or Vec<&'static str>??
or something like that. This is because Rust's grammar is more powerful than regexes -- it is mostly context-free with some context-sensitive parts (link).
What you're probably looking for is some sort of declarative and syntactical replacement from ($t:ty) \? \? => Option<$t>
.
In addition, this regex can also probably match on non-types like a??
if a: Option<Option<T>>
.
If you wanted to create a special syntax for this, you'd probably do something like:
macro_rules! shorthand_struct_fields {
/* rows of idents to types and then adjust struct definition but with T?? substituted for Option<T> */
}
struct Foo {
shorthand_struct_fields! {
x: i32??,
}
}
I'm not sure if this is such a good idea, but it you do want to create this large macro, you would be best suited by writing a declarative macros with sub-macros that use @
rules, like so: http://danielkeep.github.io/tlborm/book/pat-internal-rules.html
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论