69 lines
1.4 KiB
Rust
69 lines
1.4 KiB
Rust
|
|
use std::sync::Arc;
|
||
|
|
use std::thread;
|
||
|
|
|
||
|
|
// Обобщённое выражение: I -> Out
|
||
|
|
pub trait Expr<I> {
|
||
|
|
type Out;
|
||
|
|
fn eval(&self, x: I) -> Self::Out;
|
||
|
|
}
|
||
|
|
|
||
|
|
// атомарная функция
|
||
|
|
pub struct Function<I, O> {
|
||
|
|
pub f: fn(I) -> O,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<I, O> Expr<I> for Function<I, O> {
|
||
|
|
type Out = O;
|
||
|
|
fn eval(&self, x: I) -> O {
|
||
|
|
(self.f)(x)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// композиция g∘f
|
||
|
|
pub struct Composition<F1, F2> {
|
||
|
|
pub first: F1,
|
||
|
|
pub second: F2,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<I, F1, F2> Expr<I> for Composition<F1, F2>
|
||
|
|
where
|
||
|
|
F1: Expr<I>,
|
||
|
|
F2: Expr<F1::Out>,
|
||
|
|
{
|
||
|
|
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<F1, F2> {
|
||
|
|
pub left: Arc<F1>,
|
||
|
|
pub right: Arc<F2>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<I, F1, F2> Expr<I> for Junction<F1, F2>
|
||
|
|
where
|
||
|
|
I: Copy + Send + 'static,
|
||
|
|
F1: Expr<I> + Send + Sync + 'static,
|
||
|
|
F2: Expr<I> + 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())
|
||
|
|
}
|
||
|
|
}
|