我想根据一个域匹配一个复杂常数。如果在另一个模式上选择一个常量,则不允许在另一个模式上选择一个常量。
是否可以编写一个宏,将常量表达式的结果在编译时“内联”以使生成的代码是有效的LiteralPattern
?
考虑以下工作代码:
pub struct Instruction {
code: u8,
width: usize,
}
pub const CMP_REG_U8: Instruction = Instruction { code: 3, width: 3 };
pub const CMP_REG_U32: Instruction = Instruction { code: 4, width: 6 };
pub const INVALID: Instruction = Instruction { code: 0, width: 0 };
fn main() {
let opcode = 3u8;
let inst = match opcode {
3 => CMP_REG_U8,
4 => CMP_REG_U32,
_ => INVALID,
};
println!("inst.code: {} inst.width: {}", inst.code, inst.width);
}
我希望能够基本上写下:
let inst = match opcode {
CMP_REG_U8.code => CMP_REG_U8,
CMP_REG_U32.code => CMP_REG_U32,
_ => INVALID,
};
这样,我就不必在我的比赛陈述中输入神奇的数字,也不必重复第二次。
我意识到我可以使用警卫:
let inst = match opcode {
x if x == CMP_REG_U8.code => CMP_REG_U8,
x if x == CMP_REG_U32.code => CMP_REG_U32,
_ => INVALID,
};
...但这似乎有点冗长,我关心的是如何说服编译器给我一个跳转表实现。(想象一下,与将值硬编码为文本相比,我们不只是返回指令,而是希望执行一段代码,并能够引用相关数据,如inst.width
)
所以底线是,有没有可能用一个“文字化”常量的宏来解决这个问题?
let inst = match opcode {
as_literal!(CMP_REG_U8.code) => exec_op(CMP_REG_U8),
as_literal!(CMP_REG_U32.code) => exec_op(CMP_REG_U32),
_ => INVALID,
};
这样,匹配臂都将是硬编码的整数,这将使编译器非常容易内联exec_op
所做的任何事情,将宽度
等识别为该上下文中的常量,并执行计算的goto或其他任何操作。
我听说Rust中的宏只允许你做你本可以自己打字的事情。然而,我当然可以输入3
,而不是CMP_REG_U8。代码
——问题是锈能不能帮我。它需要在编译时解决这个问题,以使生成的模式在匹配中有效。
可以使用一个宏生成另一个宏:
macro_rules! define_consts {
($(
$vis: vis const $name: ident : Instruction = Instruction { code: $code: literal, width: $width: literal };
)*) => {
$(
$vis const $name: Instruction = Instruction { code: $code, width: $width };
)*
macro_rules! as_literal {
$(($name . code) => { $code });*
}
}
}
用你的常量定义来称呼它:
define_consts! {
pub const CMP_REG_U8: Instruction = Instruction { code: 3, width: 3 };
pub const CMP_REG_U32: Instruction = Instruction { code: 4, width: 6 };
pub const INVALID: Instruction = Instruction { code: 0, width: 0 };
}
将生成写入的常量,以及一个宏as_literal!
,它可以执行您想要的操作:
fn exec_op(inst: Instruction) -> Instruction {
inst
}
fn main() {
let opcode = 3u8;
let inst = match opcode {
as_literal!(CMP_REG_U8.code) => exec_op(CMP_REG_U8),
as_literal!(CMP_REG_U32.code) => exec_op(CMP_REG_U32),
_ => INVALID,
};
println!("inst.code: {} inst.width: {}", inst.code, inst.width); // 3
}
不过,我不确定这有多有价值!鉴于模式都是文字,使用if...否则if...
而不是匹配
最终可能会生成相同的程序集。
我想编写一个由文件路径参数化的宏。在编译时,它读取该文件并根据其内容发出Rust代码。这可能吗? 我发现但不清楚我如何在编译时使用它的结果,而不是将内容按原样拼接到生成的代码中。
问题内容: 是否可以创建内联伪样式? 例如,我可以做以下事情吗? 这背后的原因是我正在开发一个创建UI元素的.NET库。我想生成无需设置外部样式表即可设置其悬停状态的HTML元素。 问题答案: 不幸的是,不能,您不能使用内联CSS来实现悬停效果。 此问题的(较差)解决方法是让控件在呈现时呈现样式块。例如,您的控件可以呈现为: 如果您可以强迫用户在页面顶部放置“样式控件”,则可以在其中渲染所有自定义
问题内容: 有谁知道我们可以通过XML工具从XML模式生成JSON模式或通过Java从JSON模式生成XML模式的工具或方法? 问题答案: 它不是很优雅,但是jackson可以从java类生成json模式。因此,您可以使用xml模式,并使用jaxb注释从中生成java类,然后从其中生成json模式,因为jackson支持jaxb注释。
我有一个JS项目,它使用aws服务作为后端(Cognito、AppSync、S3等)。 我使用AWS Amplify访问这些服务,但不使用Amplify CLI;所有aws服务都是手动配置的。 关于AppSync,我有一个小脚本,它读取模式(从APPESNC控制台手动下载),然后生成TypeScript操作和操作类型文件(使用放大器-图形ql-文档-生成器和放大器-图形ql-类型-生成器)。 有没
valgrind快速启动页面提到: 这将我引向这样一个问题:是否有充分的理由不在生产中从程序中消除这样的错误?发布包含此类错误的程序有什么好处吗?如果有,开发人员如何保护它的安全,尽管据我所知,包含此类错误的程序可以不可预测地运行,并且无法对其行为做出一般假设?如果是这样,你能提供真实世界的例子,说明程序运行时有这些错误比没有错误更好吗?