让我们假设,我们需要一串常量,将棋盘的每个方格与它的坐标相关联,这样我们就可以在我们的锈蚀代码中使用这些常量。
这样的定义之一可以是:
#[allow(dead_code)]
const A1: (usize,usize) = (0, 0);就会有64人。
现在,作为emacs用户,我可以轻松地生成源代码,例如:
(dolist (col '(?A ?B ?C ?D ?E ?F ?G ?H))
(dolist (row '(?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8))
(insert "#[allow(dead_code)]")
(end-of-line)
(newline-and-indent)
(insert "const " col row ": (usize,usize) = ("
(format "%d" (- col ?A))
", "
(format "%d" (- row ?1))
");")
(end-of-line)
(newline-and-indent)))有了缺点,现在我的文件增加了128条特别无聊的行。
在通用Lisp中,我会通过定义宏来解决这个问题,例如:
(defmacro defconst-square-names ()
(labels ((square-name (row col)
(intern
(format nil "+~C~D+"
(code-char (+ (char-code #\A) col))
(+ row 1))))
(one-square (row col)
`(defconstant ,(square-name row col)
(cons ,row ,col))))
`(eval-when (:compile-toplevel :load-toplevel :execute)
,@(loop
for col below 8
appending
(loop for row below 8
collecting (one-square row col))))))
(defconst-square-names) ;; nicer packaging of those 64 boring lines...现在,问题出现了,当然,
如果
更新
@aedm用关于seq-macro板条箱的评论向我指出了我第一次尝试完成它。但是不幸的是,在浏览有关宏的各种Rust文档之后,我仍然不知道如何在这样一个宏中定义和调用编译时函数:
fn const_name(index:usize) -> String {
format!("{}{}",
char::from_u32('A' as u32
+ (index as u32 % 8)).unwrap()
, index / 8)
}
seq!(index in 0..64 {
#[allow(dead_code)]
const $crate::const_name(index) : (usize,usize) = ($(index / 8), $(index %8));
});在我的Common解决方案中,我只是在宏中定义了本地函数来完成这些工作。生锈的方式是什么?
发布于 2022-03-12 00:41:21
这里有一种只使用macro_rules! (“宏示例”)和paste机箱(构造标识符)的方法。它不是特别优雅,但它相当短,不需要您编写一个proc宏机箱。
由于macro_rules!不会算术,所以需要使用所有涉及的符号来调用它。(也许seq-macro会在这方面有所帮助,但我并不熟悉。)
use paste::paste;
macro_rules! board {
// For each column, call column!() passing the details of that column
// and all of the rows. (This can't be done in one macro because macro
// repetition works like "zip", not like "cartesian product".)
( ($($cols:ident $colnos:literal),*), $rows:tt ) => {
$( column!($cols, $colnos, $rows); )*
};
}
/// Helper for board!
macro_rules! column {
( $col:ident, $colno:literal, ($($rows:literal),*) ) => {
$(
paste! {
// [< >] are special brackets that tell the `paste!` macro to
// paste together all the pieces appearing within them into
// a single identifier.
#[allow(dead_code)]
const [< $col $rows >]: (usize, usize) = ($colno, $rows - 1);
}
)*
};
}
board!((A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7), (1, 2, 3, 4, 5, 6, 7, 8));
fn main() {
dbg!(A1, A8, H1, H8);
}https://stackoverflow.com/questions/71443259
复制相似问题