use std::sync::Arc; use std::thread; // Обобщённое выражение: I -> Out pub trait Expr { type Out; fn eval(&self, x: I) -> Self::Out; } // атомарная функция pub struct Function { pub f: fn(I) -> O, } impl Expr for Function { type Out = O; fn eval(&self, x: I) -> O { (self.f)(x) } } // композиция g∘f pub struct Composition { pub first: F1, pub second: F2, } impl Expr for Composition where F1: Expr, F2: Expr, { type Out = F2::Out; fn eval(&self, x: I) -> Self::Out { let mid = self.first.eval(x); self.second.eval(mid) } } // junction — две ветки параллельно pub struct Junction { pub left: Arc, pub right: Arc, } impl Expr for Junction where I: Copy + Send + 'static, F1: Expr + Send + Sync + 'static, F2: Expr + Send + Sync + 'static, F1::Out: Send + 'static, F2::Out: Send + 'static, { type Out = (F1::Out, F2::Out); fn eval(&self, x: I) -> (F1::Out, F2::Out) { let l = Arc::clone(&self.left); let r = Arc::clone(&self.right); let x1 = x; let x2 = x; let h1 = thread::spawn(move || l.eval(x1)); let h2 = thread::spawn(move || r.eval(x2)); (h1.join().unwrap(), h2.join().unwrap()) } }