Latest version Documentation MSRV License
extfn is a Rust library that implements extension functions, allowing any* freestanding function to
be called as a.foo(b) instead of foo(a, b) just by adding #[extfn] and renaming the first parameter to self.
use extfn::extfn; use std::cmp::Ordering; use std::fmt::Display; #[extfn] fn factorial(self: u64) -> u64 { (1..=self).product() } #[extfn] fn string_len(self: impl Display) -> usize { format!("{self}").len() } #[extfn] fn sorted_by<T: Ord, F>(mut self: Vec<T>, compare: F) -> Vec<T> where F: FnMut(&T, &T) -> Ordering, { self.sort_by(compare); self } fn main() { assert_eq!(6.factorial(), 720); assert_eq!(true.string_len(), 4); assert_eq!(vec![2, 1, 3].sorted_by(|a, b| b.cmp(a)), vec![3, 2, 1]); }
Click here to expand macros
use extfn::extfn; use std::cmp::Ordering; use std::fmt::Display; trait factorial { fn factorial(self) -> u64; } impl factorial for u64 { fn factorial(self) -> u64 { (1..=self).product() } } trait string_len<_T1> { fn string_len(self) -> usize where _T1: Display; } impl<_T1> string_len<_T1> for _T1 { fn string_len(self) -> usize where _T1: Display, { format!("{self}").len() } } trait sorted_by<T> { fn sorted_by<F>(self, dummy1: F) -> Vec<T> where F: FnMut(&T, &T) -> Ordering, T: Ord; } impl<T> sorted_by<T> for Vec<T> { fn sorted_by<F>(mut self, compare: F) -> Vec<T> where F: FnMut(&T, &T) -> Ordering, T: Ord, { self.sort_by(compare); self } } fn main() { assert_eq!(6.factorial(), 720); assert_eq!(true.string_len(), 4); assert_eq!(vec![2, 1, 3].sorted_by(|a, b| b.cmp(a)), vec![3, 2, 1]); }
A list of all supported function signatures can be found in tests/signatures.rs. Nearly everything I could think of is supported, with a few exceptions (see Fine Print).
Please report any edge cases where the "extfn transform" (add #[extfn] and rename the first parameter to self)
doesn't work.
The #[extfn] macro essentially just converts a function into an extension trait with a single method.
This trait shares it's name with the extension function, allowing us to mark extension functions as pub and to import
them just like regular functions using use example::add1;, maintaining the illusion:
mod example { use extfn::extfn; #[extfn] pub fn add1(self: usize) -> usize { self + 1 } } use example::add1; fn main() { assert_eq!(1.add1(), 2); }
Extension functions are already implemented in other programming languages:
As a Rust feature, extension functions have been proposed here, here, here, here.
- Const functions are unsupported because of E0379
self: T::Associs unsupported