Macro adapton::memo [] [src]

macro_rules! memo {
    ( [ $nmop:expr ] ? $fun:expr ; $( $lab:ident :$arg:expr ),* ) => { ... };
    ( $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => { ... };
    ( $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => { ... };
    ( $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => { ... };
    ( $f:path , $( $lab:ident : $arg:expr ),* ) => { ... };
    ( $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => { ... };
    ( $nm:expr =>> $f:ident =>> < $( $ty:ty ),* > , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => { ... };
}

Memoization

Memoization provides a mechanism for caching the results of subcomputations; it is a crtical feature of Adapton's approach to incremental computation.

In Adapton, each memoization point has three ingredients:

  • A function expression (of type Fn)

  • Zero or more arguments. Each argument type must have an implementation for the traits Eq + Clone + Hash + Debug. The traits Eq and Clone are both critical to Adapton's caching and change propagation engine. The trait Hash is required when Adapton's naming strategy is structural (e.g., where function names are based on the hashes of their arguments). The trait Debug is useful for debugging, and reflection.

  • An optional name, which identifies the function call for reuse later.

    • When this optional name is None, the memoization point may be treated in one of two ways: either as just an ordinary, uncached function call, or as a cached function call that is identified structurally, by its function pointer and arguments. Adapton permits structural subcomputations via the engine's structural function.

    • When this is Some(name), the memoization point uses name to identify the work performed by the function call, and its result. Critically, in future incremental runs, it is possible for name to associate with different functions and/or argument values.

Optional name version

The following form is preferred:

memo!( [ optional_name ]? fnexp ; lab1 : arg1, ..., labk : argk )

It accepts an optional name, of type Option<Name>, and an arbitrary function expression fnexp (closure or function pointer). Like the other forms, it requires that the programmer label each argument.

Example

let opnm  : Option<Name> = Some(name_unit());
let (t,z) : (Art<usize>, usize) = 
  memo!([opnm]?
    |x:usize,y:usize|{ if x > y { x } else { y }};
     x:10,   y:20   );

assert_eq!(z, 20);
assert_eq!(force(&t), 20);