init
Co-authored-by: yandros <[email protected]>
Co-authored-by: nemo <[email protected]>
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.lock | 7 | ||||
| -rw-r--r-- | Cargo.toml | 6 | ||||
| -rw-r--r-- | src/lib.rs | 51 |
4 files changed, 65 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e350587 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bind" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b4eed99 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bind" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..383bc90 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,51 @@ +#![feature(tuple_trait, unboxed_closures, fn_traits)] +#![allow(private_bounds)] +use core::ops::FnMut; +use std::marker::Tuple; + +trait Head: Tuple { + type Head; + type Tail: Tuple; + + fn rejoin(_: Self::Head, _: Self::Tail) -> Self; +} + +macro_rules! impls {( + $($Hd:tt $($Tail:tt)*)? +) => ($(impls!($($Tail)*);)?$( +impl<$Hd $(, $Tail)*> Head for ($Hd, $($Tail),*) { + type Head = $Hd; + type Tail = ($($Tail, )*); + fn rejoin($Hd: Self::Head, tail: Self::Tail) -> Self { + let ($($Tail, )*) = tail; + ($Hd, $($Tail),*) + } +})?)} +impls![_13 _12 _11 _10 _9 _8 _7 _6 _5 _4 _3 _2 _1 _0]; + +impl<Args: Head, F: FnMut<Args> + Sized> Bind<Args> for F {} +pub trait Bind<Args: Head>: FnMut<Args> + Sized { + fn bind<T: Clone>(self, with: T) -> impl FnMut<Args::Tail, Output = Self::Output> + where + Args: Head<Head = T>, + { + return Fn { f: self, t: with }; + struct Fn<Args: Head, F: FnMut<Args>> { + f: F, + t: Args::Head, + } + impl<Args: Head, F: FnMut<Args>> FnOnce<Args::Tail> for Fn<Args, F> { + type Output = F::Output; + extern "rust-call" fn call_once(mut self, args: Args::Tail) -> Self::Output { + let args = Args::rejoin(self.t, args); + self.f.call_mut(args) + } + } + impl<Args: Head<Head: Clone>, F: FnMut<Args>> FnMut<Args::Tail> for Fn<Args, F> { + extern "rust-call" fn call_mut(&mut self, args: Args::Tail) -> Self::Output { + let args = Args::rejoin(self.t.clone(), args); + self.f.call_mut(args) + } + } + } +} |