Rust预处理器:类似于 #define 的纯文本替换,用于简化语法。

huangapple go评论62阅读模式
英文:

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&lt;$1&gt; to simplify optional type syntax.

For example, the following struct

struct ReturnPath {
    name: Option&lt;String&gt;,
    file_type: Option&lt;String&gt;,
    mtime: Option&lt;i64&gt;
}

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&lt;T, R&gt;??Vec&lt;&amp;&#39;static str&gt;?? 等情况。这是因为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) \? \? =&gt; Option&lt;$t&gt;.
你可能正在寻找的是一种从 ($t:ty) \? \? =&gt; Option&lt;$t&gt; 进行声明性和语法替换的方式。

In addition, this regex can also probably match on non-types like a?? if a: Option&lt;Option&lt;T&gt;&gt;.
此外,如果 a: Option&lt;Option&lt;T&gt;&gt;,这个正则表达式可能也能匹配非类型的内容,比如 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&lt;T&gt; */

}

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&lt;T, R&gt;?? or Vec&lt;&amp;&#39;static str&gt;?? 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) \? \? =&gt; Option&lt;$t&gt;.

In addition, this regex can also probably match on non-types like a?? if a: Option&lt;Option&lt;T&gt;&gt;.

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&lt;T&gt; */

}

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

huangapple
  • 本文由 发表于 2023年2月18日 01:57:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75487754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定