Skip to content

Instantly share code, notes, and snippets.

@Ciantic
Created February 11, 2023 17:05
Show Gist options
  • Save Ciantic/e4abf23b4089bad1f367fddcc35a9825 to your computer and use it in GitHub Desktop.
Save Ciantic/e4abf23b4089bad1f367fddcc35a9825 to your computer and use it in GitHub Desktop.
Two examples: How to decorate (curry) a function and how to curry a method in Rust
// Cargo.toml
//
// [dependencies]
// macro_rules_attribute = "0.1"
#[macro_use]
extern crate macro_rules_attribute;
// How to decorate a function
//
// Taken from here: https://users.rust-lang.org/t/are-derive-macros-in-rust-similar-to-decorators-in-python/46686/4
macro_rules! memoize {(
$( #[$attr:meta] )*
$pub:vis
fn $fname:ident (
$( $arg_name:ident : $ArgTy:ty ),* $(,)?
) $( -> $RetTy:ty)?
$body:block
) => (
$( #[$attr] )*
#[allow(unused_parens)]
$pub
fn $fname (
$( $arg_name : $ArgTy ),*
) $(-> $RetTy)?
{
/// Re-emit the original function definition, but as a scoped helper
$( #[$attr] )*
fn __original_func__ (
$($arg_name: $ArgTy),*
) $(-> $RetTy)?
$body
::std::thread_local! {
static CACHE
: ::std::cell::RefCell<
::std::collections::HashMap<
( $($ArgTy ,)* ),
( $($RetTy)? ),
>
>
= ::std::default::Default::default()
;
}
CACHE.with(|cache| {
let args = ($($arg_name ,)*);
if let Some(value) = cache.borrow().get(&args) {
return value.clone();
}
let ($($arg_name ,)*) = args.clone();
let value = __original_func__($($arg_name),*);
cache.borrow_mut().insert(args, ::std::clone::Clone::clone(&value));
value
})
}
)}
#[apply(memoize!)]
fn fibo (n: u64) -> u64
{
dbg!(n);
if n <= 1 { n } else { fibo(n - 1) + fibo(n - 2) }
}
// How to decorate a method
//
// This example I made up, I wanted to know can we decorate a method, and it works!
macro_rules! my_decorate_method_example {(
$( #[$attr:meta] )*
$pub:vis
fn $fname:ident (
&$self_:ident, $( $arg_name:ident : $ArgTy:ty ),* $(,)?
) $( -> $RetTy:ty)?
$body:block
) => (
$( #[$attr] )*
#[allow(unused_parens)]
$pub
fn $fname (
&$self_, $( $arg_name : $ArgTy ),*
) $(-> $RetTy)?
{
let value = $body;
value + 100
}
)}
struct SomeThing {
foo: u64,
}
impl SomeThing {
#[apply(my_decorate_method_example!)]
pub fn some_method (&self, n: u64) -> u64
{
n + 100 + self.foo
}
}
fn main ()
{
dbg!(fibo(5));
let foo = SomeThing { foo: 100 };
dbg!(foo.some_method(100));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment