bobtail
Generate macro proxies of functions whose tails can be "bobbed" as in cut off.
This crate produces macro proxies of functions whose trailing arguments may be omitted or provided with less boilerplate.
Prototypes
The define! macro generates macro proxies for functions and method prototypes.
Free Functions
define!
assert_eq!; // Call function.
assert_eq!; // Call macro with omission.
assert_eq!; // Call macro with explicit omission.
assert_eq!; // Pass unwrapped second argument.
# assert_eq!; // Pass wrapped second argument.
Generated Macro Rules
The bobtail::define! produces macro rules that might have looked like this code.
But bobtail::define! can handle the following case, which the above macro can
not.
assert_eq!; // Pass wrapped second argument.
How? Because instead of being restricted to Option, an ommitable parameter can
be any type that implements Default and From<T>. What bobtail::define!
actually produces is this:
From<T> is not only more flexible, but it permits one to use Some(2) above
because there is a blanket implementation for From<T> for all T, which is an
identity function.
Methods
Methods with a &self, &mut self, or self expect the receiver as the first
argument to the macro.
;
define!
let a = A;
assert_eq!; // Call function.
assert_eq!; // Call macro.
assert_eq!; // Omit `Some`.
assert_eq!; // Omit second argument.
assert_eq!; // Explicitly omit second argument.
assert_eq!; // Consume self.
let a = A;
assert_eq!; // Any `Default` will do.
Attributes
One can also generate macro proxies with attributes.
Free Functions
assert_eq!; // Call function.
assert_eq!; // Call macro with omission.
assert_eq!; // Call macro with explicit omission.
assert_eq!; // Pass unwrapped second argument.
# assert_eq!; // Pass wrapped second argument.
Methods
Methods with a &self, &mut self, or self expect the receiver as the first
argument to the macro proxy.
;
let a = A;
assert_eq!; // Call function.
assert_eq!; // Call macro.
assert_eq!; // Omit `Some`.
assert_eq!; // Omit second argument.
assert_eq!; // Explicitly omit second argument.
assert_eq!; // Consume self.
let a = A;
assert_eq!; // Any `Default` will do.
Motivation and Justification
This crate was inspired by my work on
Nano-9, a Pico-8 compatibility layer for
Bevy. Pico-8's Lua API has many arguments that are often omitted. Consider
Pico-8's text drawing function print.
-- print(str, [x,] [y,] [color])
print
-- No x? No y? No problem.
Nano-9 provides the Lua API as-is, but it also provides a Pico-8-like API in Rust for which the above looks like this:
// print(str, vec2, color, /* Nano-9 extensions: */ font_size, font_index)
pico8.print.unwrap;
The aim of this crate is to offer an API on the Rust side that is not so verbose.
print!.unwrap;
A Caution
This is my reason for creating this crate, but that does not mean I wholeheartly endorse this kind of positional, omittable, API design. If I were not constrained by Pico-8's initial design and wanting to bear a strong resemblance to it, I would consider using structs expressively as named and omittable arguments potentially using other crates like typed-builder and derive_builder.
Install
Add bobtail to a project with the following command:
License
This crate is licensed under the MIT License or the Apache License 2.0.