-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Hi @LyonSyonII,
First of all, thanks for creating akin. I like the approach quit a lot.
I'm wondering if global substitutions, and generating items only once can be added to akin.
An example describes the use case best:
Imagine we would like to create an extension trait for serde_json::Value that adds methods like into_xy methods that return owned values.
I'd create and implement a trait like this:
trait ValueExt {
fn into_null(self) -> Result<(), Self>;
fn into_bool(self) -> Result<bool, Self>;
fn into_array(self) -> Result<Vec<Value>, Self>;
// etc...
}
impl ValueExt for Value {
fn into_null(self) -> Result<(), Self> { todo!()}
fn into_bool(self) -> Result<bool, Self> { todo!()}
fn into_array(self) -> Result<Vec<Value>, Self> { todo!()}
// etc...
}Instead of writing all of this by hand, I'd like to use akin to generate the trait and the trait implementation:
akin::akin! {
let &ident = [ null, bool, array, /* ... */ ];
let &Type = [
{ () },
{ bool },
{ Vec<Value> },
// ...
];
trait JsonValueExt {
fn into_~*ident(self) -> Result<*Type, Self>;
}
impl ValueExt for serde_json::Value {
fn into_~*ident(self) -> Result<*Type, Self> { todo!() }
}
}But of course this doesn't work (JsonValueExt is defined several times).
I'm wondering if this use case somehow can be supported.
For example via something like this:
akin::akin! {
// ...
#[akin(context)]
trait JsonValueExt {
// A new `akin` context
fn into_~*ident(self) -> Result<*Type, Self>;
}
// ...
}#[akin(context)] would tell akin to generate the decorated item only once, and substitute within the item (similar to how $($ident)+ works for macro_rules macros). Something like akin_context! { /* new context */ } probably also would be useful, for cases where attributes can't be used.
My first idea for a name of the new attribute was inner, but I think that wouldn't be ideal, because it should be possible to substitute things within the trait definition itself (e.g. for generic traits). Maybe there is a better name than context, however.
Similarly, the duplicate crate has a nice feature to define global substitutions, which often come in handy.
I'm wondering if this can be supported via something like:
akin::akin! {
// ...
const &foo = { println!("Hello, world!") };
*foo
// ...
}...which would expand to just one println!("Hello, world!").
Using const here would be perfect semantically, I believe.
These features would make akin useful in even more cases.
Currently, I have created an additional macro_rules macro to generate the trait definition (duplicating the &Type and &ident definitions), which works but is not really ideal.
Would it be possible to add these features?
Currently, I haven't learned how to use procedural macros, so I currently can't add these features myself. But if you don't want to add this yourself, but would accept a PR, I could do this when I learn procedural macros at some point (however, that would most likely be at least several months into the future, if not more).
Thanks again for creating akin!