Mercurial > lbo > hg > memoize
changeset 69:0ada62444b37
Merge pull request #10 from bijij/master
Add support for pattern binding to function arguments
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 01 Jan 2022 12:29:34 +0100 |
parents | aefbc4424cb6 (current diff) bf87b6014441 (diff) |
children | 3adb990ef496 |
files | |
diffstat | 2 files changed, 37 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/patterns.rs Sat Jan 01 12:29:34 2022 +0100 @@ -0,0 +1,25 @@ +use memoize::memoize; + +// Patterns in memoized function arguments must be bound by name. +#[memoize] +fn manhattan_distance(_p1 @ (x1, y1): (i32, i32), _p2 @ (x2, y2): (i32, i32)) -> i32 { + (x1 - x2).abs() + (y1 - y2).abs() +} + +#[derive(Clone, PartialEq, Eq, Hash)] +enum OnlyOne { + Value(i32), +} + +#[memoize] +fn get_value(_enum @ OnlyOne::Value(value): OnlyOne) -> i32 { + value +} + +fn main() { + // `manhattan_distance` is only called once here. + assert_eq!(manhattan_distance((1, 1), (1, 3)), 2); + + // Same with `get_value`. + assert_eq!(!get_value(OnlyOne::Value(0)), 0); +}
--- a/inner/src/lib.rs Fri Dec 24 13:40:28 2021 +0100 +++ b/inner/src/lib.rs Sat Jan 01 12:29:34 2022 +0100 @@ -201,7 +201,7 @@ // Extracted from the function signature. let input_types: Vec<Box<syn::Type>>; - let input_names: Vec<Box<syn::Pat>>; + let input_names: Vec<syn::Ident>; let return_type; match check_signature(sig) { @@ -221,7 +221,7 @@ // Construct storage for the memoized keys and return values. let store_ident = syn::Ident::new(&map_name.to_uppercase(), sig.span()); - let (cache_type, cache_init) = store::construct_cache(&attr, input_tuple_type, return_type); + let (cache_type, cache_init) = store::construct_cache(&attr, input_tuple_type, return_type.clone()); let store = quote::quote! { ::memoize::lazy_static::lazy_static! { static ref #store_ident : std::sync::Mutex<#cache_type> = @@ -234,6 +234,10 @@ renamed_fn.sig.ident = syn::Ident::new(&renamed_name, func.sig.span()); let memoized_id = &renamed_fn.sig.ident; + // Extract the function name and identifier. + let fn_name = func.sig.ident.clone(); + let fn_vis = func.vis.clone(); + // Construct memoizer function, which calls the original function. let syntax_names_tuple = quote::quote! { (#(#input_names),*) }; let syntax_names_tuple_cloned = quote::quote! { (#(#input_names.clone()),*) }; @@ -276,7 +280,9 @@ }; #[cfg(not(feature = "full"))] let memoizer = quote::quote! { - #sig { + #fn_vis fn #fn_name ( + #(#input_names: #input_types),* + ) -> #return_type { { let mut hm = &mut #store_ident.lock().unwrap(); if let Some(r) = hm.#get_fn(&#syntax_names_tuple_cloned) { @@ -302,7 +308,7 @@ fn check_signature( sig: &syn::Signature, -) -> Result<(Vec<Box<syn::Type>>, Vec<Box<syn::Pat>>), syn::Error> { +) -> Result<(Vec<Box<syn::Type>>, Vec<syn::Ident>), syn::Error> { if let syn::FnArg::Receiver(_) = sig.inputs[0] { return Err(syn::Error::new( sig.span(), @@ -316,8 +322,8 @@ if let syn::FnArg::Typed(ref arg) = a { types.push(arg.ty.clone()); - if let syn::Pat::Ident(_) = &*arg.pat { - names.push(arg.pat.clone()); + if let syn::Pat::Ident(patident) = &*arg.pat { + names.push(patident.ident.clone()); } else { return Err(syn::Error::new( sig.span(),