应如何定义const container = document.querySelector('#container');
const ball = document.querySelector('#ball');
let mover = 5;
window.addEventListener('load', () => {
ball.style.position = 'relative';
ball.style.left = 0;
ball.style.top = 0;
});
window.addEventListener('keydown', (e) => {
switch(e.key) {
case 'ArrowUp' :
ball.style.top = parseInt(ball.style.top) - mover + '%';
if(ball.style.left == '100%') {
alert('dont move');
}
break;
case 'ArrowDown' :
ball.style.top = parseInt(ball.style.top) + mover + '%';
break;
case 'ArrowRight' :
ball.style.left = parseInt(ball.style.left) + mover + '%';
break;
case 'ArrowLeft' :
ball.style.left = parseInt(ball.style.left) - mover + '%';
break;
}
});
使其“返回” 5?
a_proc_macro
答案 0 :(得分:3)
在The Rust Programming Language's上阅读macros一章说:
类似于函数的宏定义看起来像函数调用的宏。类似于
fn main() { let a = a_proc_macro!(); assert!(a == 5); }
宏,它们比函数更灵活;例如,他们 可以接受未知数量的参数。但是,macro_rules!
宏可以是 仅使用我们在本节中讨论的类似匹配语法定义 “Declarative Macros withmacro_rules!
for General Metaprogramming” 较早。类似函数的宏带有一个macro_rules!
参数, 定义使用Rust代码作为其他两个来操纵TokenStream
程序宏的类型。类似函数的宏的一个示例是TokenStream
可以这样称呼宏:sql!
此宏将解析其中的SQL语句,并检查其是否 语法正确,这比
let sql = sql!(SELECT * FROM posts WHERE id=1);
宏可以做到。macro_rules!
宏的定义如下:sql!
此定义类似于自定义衍生宏的签名:我们收到 括号内的标记并返回我们想要的代码 生成。
#[proc_macro]
pub fn sql(input: TokenStream) -> TokenStream {
Cargo.toml
example
├── Cargo.toml
├── example-macro
│ ├── Cargo.toml
│ ├── src
│ │ └── lib.rs
├── src
│ └── main.rs
src / main.rs
[package]
name = "example"
version = "0.1.0"
edition = "2018"
[dependencies]
example-macro = { path = "example-macro" }
从Rust 1.39开始,您不能在模块的顶层(包括板条箱的根模块)的顶层调用任何类似于函数的过程宏。如果您想将其用作表达式,则需要每晚使用Rust。
example-macro / Cargo.toml
#![feature(proc_macro_hygiene)]
fn main() {
assert_eq!(example_macro::a_proc_macro!(), 5);
}
example-macro / src / lib.rs
[package]
name = "example-macro"
version = "0.1.0"
edition = "2018"
[lib]
proc-macro = true
另请参阅:
答案 1 :(得分:1)
在稳定的Rust中尚无法直接定义类似于表达式的过程宏。如果您可以每晚使用,Shepmaster's answer会显示如何使用。
如果您处于稳定状态,仍然可以按以下方式模拟类似于表达式的过程宏:
在您的情况下,您将这样定义程序宏:
#[proc_macro]
pub fn a_proc_macro_impl(_input: TokenStream) -> TokenStream {
"fn output() -> usize { 5 }".parse().unwrap()
}
...帮助程序macro_rules!
宏遵循以下模式:
macro_rules! a_proc_macro {
($($t:tt)*) => {{
struct _X;
impl _X {
a_proc_macro!($($t)*);
}
_X::output()
}}
}
这是一个hack,也是一个繁琐的hack,但是proc-macro-hack板条箱可以提供帮助,并且可以更轻松地使用上述技术生成程序宏。借助proc-macro-hack
板条箱,您可以在稳定状态下运行Shepmaster的答案中几乎不变的代码:
Cargo.toml
文件,并将proc-macro-hack = "0.5.11"
添加到依赖项部分; #[proc_macro_hack] use example_macro::a_proc_macro;
中添加src/main.rs
,然后从本地名称空间调用a_proc_macro!
。#[proc_macro_hack::proc_macro_hack]
中a_proc_macro
的定义之前添加example-macro/src/lib.rs
。