1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
//! クロージャの wrapper クラス。
use super::super::traits::binop;
use std::fmt::Debug;
use binop::{Associative, Identity, Magma};
/// 任意の結合的な演算を持つ。
///
/// 結合性については使用者側に保証してもらう。
///
/// # Examples
/// ```
/// use std::cell::RefCell;
///
/// use nekolib::traits::{Magma, Identity};
/// use nekolib::utils::OpClosure;
///
/// let runtime_mod = 10;
/// let op_memo = RefCell::new(vec![]);
/// let id_times = RefCell::new(0);
/// let op_cl = OpClosure::new(|x: i32, y| {
/// op_memo.borrow_mut().push((x, y));
/// (x + y).rem_euclid(runtime_mod)
/// }, || {
/// *id_times.borrow_mut() += 1;
/// 0
/// });
///
/// assert_eq!(op_cl.op(1, 9), 0);
/// assert_eq!(op_cl.op(3, 8), 1);
/// assert_eq!(op_cl.op(-5, -3), 2);
/// assert_eq!(op_cl.id(), 0);
///
/// assert_eq!(*op_memo.borrow(), [(1, 9), (3, 8), (-5, -3)]);
/// assert_eq!(*id_times.borrow(), 1);
/// ```
#[derive(Clone, Copy, Debug, Default)]
pub struct OpClosure<T, Op: Fn(T, T) -> T, Id: Fn() -> T>(Op, Id);
impl<T: Eq, Op: Fn(T, T) -> T, Id: Fn() -> T> OpClosure<T, Op, Id> {
pub fn new(op: Op, id: Id) -> Self { Self(op, id) }
}
impl<T: Eq, Op: Fn(T, T) -> T, Id: Fn() -> T> Magma for OpClosure<T, Op, Id> {
type Set = T;
fn op(&self, lhs: T, rhs: T) -> T { (self.0)(lhs, rhs) }
}
impl<T: Eq, Op: Fn(T, T) -> T, Id: Fn() -> T> Identity
for OpClosure<T, Op, Id>
{
fn id(&self) -> T { (self.1)() }
}
impl<T: Eq, Op: Fn(T, T) -> T, Id: Fn() -> T> Associative
for OpClosure<T, Op, Id>
{
}