HexGa Map On
The core map_on! macro allows you to iterate over a list of tokens and generate repetitive code patterns.
This is particularly useful for avoiding repetitive boilerplate code when implementing traits for multiple primitive types for example.
The fundamental idea is simple: take a list of tokens and apply a macro to each one. This is useful for avoiding boilerplate when implementing traits for multiple types:
use *;
map_on!
;
Some variation of map_on exist for different use case :
use *;
map_on_number!;
Available map_on! macro :
-
map_on! -
map_on_integer_unsigned!:u8,u16,u32,u64,usize -
map_on_integer_signed!:i8,i16,i32,i64,isize -
map_on_integer: (u8,u16,u32,u64,usize) + (i8,i16,i32,i64,isize) -
map_on_float!:f32,f64 -
map_on_number!: (u8,u16,u32,u64,usize) + (i8,i16,i32,i64,isize) + (f32,f64) -
map_on_number_and_bool!: (u8,u16,u32,u64,usize) + (i8,i16,i32,i64,isize) + (f32,f64) + (bool) -
map_on_operator_binary_arithmetic_unit:Add,Sub -
map_on_operator_binary_arithmetic: (Add,Sub) + (Mul,Div,Rem) -
map_on_operator_binary_bit:BitOr,BitAnd,Shl,Shr -
map_on_operator_binary: (Add,Sub) + (Mul,Div,Rem) + (BitOr,BitAnd,Shl,Shr) -
map_on_operator_assign_arithmetic_unit:AddAssign,SubAssign -
map_on_operator_assign_arithmetic: (AddAssign,SubAssign) + (MulAssign,DivAssign,RemAssign) -
map_on_operator_assign_bit:BitOrAssign,BitAndAssign,ShlAssign,ShrAssign -
map_on_operator_assign: (AddAssign,SubAssign) + (MulAssign,DivAssign,RemAssign) + (BitOrAssign,BitAndAssign,ShlAssign,ShrAssign) -
map_on_operator_unary_bit:Not -
map_on_operator_unary_arithmetic_unit:Neg,Abs(Note :Absshould be a user defined trait, currently there isn't such a operator on the standard lib) -
map_on_operator_unary: (Not) + (Neg,Abs)
More Example
You can also use the map_on! macro to call another macro :
use *;
map_on_number!;
It is also possible to use nested map_on!*1 macro (only when using macro name, or in const context like implementing a trait) :
use *;
// Double recursive macro :)
// Do 144 trait impl in a few lines :)
map_on_number!;
Implementing a binary operator is also possible :
use *;
;
map_on_operator_binary!;
Limitation
Right now it is impossible to use the map_on! macro in a non const context (like in a function body) with lambda syntax.
The reason is that the lambda macro form will create a temporary macro with the name __map_on_inliner.
Because nested lambda map_on! macro call will generate a new macro each time with the same name __map_on_inliner, it will conflict with the previous one.
So we need a mecansime to scope the macro name.
Right now the only way to do that that I know is to use a const block, which is not ideal because it limit where the macro can be used : in a const context.
const _: = ;
https://internals.rust-lang.org/t/anonymous-modules/15441/2?u=thomas-mewily
The definiton for lambda map_on! macro is the following :
=> ;
This is the kind of stuff I was doing in C, ported to Rust while also using the full power of Rust macros.
The official name for this technique seem to be X macro, but since the main focus is mapping tokens over tokens I prefer the name map_on macro.
https://en.wikipedia.org/wiki/X_macro