Skip to main content

nekolib/utils/
op_closure.rs

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