functional programming - रस्ट में कार्यों की रचना कैसे करें?




functional-programming rust (2)

मैं एक फ़ंक्शन लिखने की कोशिश कर रहा हूं जो दो कार्यों को बनाता है। प्रारंभिक डिजाइन बहुत सरल है: एक फ़ंक्शन जो दो फ़ंक्शन लेता है और एक तैयार फ़ंक्शन देता है जिसे मैं तब अन्य फ़ंक्शन के साथ कंपोज़ कर सकता हूं, क्योंकि रस्ट में बाकी पैरामीटर नहीं हैं। मैं गैर-सहायक संकलक त्रुटियों को निराश करने के साथ निर्मित दीवार में चला गया हूं।

मेरी रचना समारोह:

fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
where
    F: 'a + Fn(A) -> B + Sized,
    G: 'a + Fn(B) -> C + Sized,
{
    Box::new(move |x| g(f(x)))
}

मैं इसका उपयोग कैसे करना चाहूंगा:

fn main() {
    let addAndMultiply = compose(|x| x * 2, |x| x + 2);
    let divideAndSubtract = compose(|x| x / 2, |x| x - 2);

    let finally = compose(*addAndMultiply, *divideAndSubtract);
    println!("Result is {}", finally(10));
}

संकलक को यह पसंद नहीं है, मैं जो भी कोशिश करता हूं, वह विशेषता सीमा कभी संतुष्ट नहीं होती है। त्रुटि है:

error[E0277]: the size for values of type `dyn std::ops::Fn(_) -> _` cannot be known at compilation time
  --> src/main.rs:13:19
   |
13 |     let finally = compose(*addAndMultiply, *divideAndSubtract);
   |                   ^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `dyn std::ops::Fn(_) -> _`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
note: required by `compose`
  --> src/main.rs:1:1
   |
1  | / fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
2  | | where
3  | |     F: 'a + Fn(A) -> B + Sized,
4  | |     G: 'a + Fn(B) -> C + Sized,
5  | | {
6  | |     Box::new(move |x| g(f(x)))
7  | | }
   | |_^

जैसा कि @ljedrz बताते हैं , इसे बनाने के लिए आपको केवल फिर से तैयार किए गए कार्यों को संदर्भित करना होगा:

let finally = compose(&*add_and_multiply, &*divide_and_subtract);

(ध्यान दें कि जंग में, कन्वेंशन तय करता है कि चर नाम snake_case में होना चाहिए)

हालाँकि, हम इसे बेहतर बना सकते हैं!

1.26 रस्ट के बाद से, हम एब्सट्रैक्ट रिटर्न टाइप्स का उपयोग कर सकते हैं (पहले चित्रित गेट #![feature(conservative_impl_trait)] रूप में #![feature(conservative_impl_trait)] )। यह आपके उदाहरण को बहुत सरल बनाने में आपकी मदद कर सकता है, क्योंकि यह आपको जीवनकाल, संदर्भों, Sized बाधाओं और Box को छोड़ने की अनुमति देता है:

fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
    F: Fn(A) -> B,
    G: Fn(B) -> C,
{
    move |x| g(f(x))
}

fn main() {
    let add_and_multiply = compose(|x| x * 2, |x| x + 2);
    let divide_and_subtract = compose(|x| x / 2, |x| x - 2);

    let finally = compose(add_and_multiply, divide_and_subtract);
    println!("Result is {}", finally(10));
}

अंत में, चूंकि आप बाकी मापदंडों का उल्लेख करते हैं, इसलिए मुझे संदेह है कि आप वास्तव में जो चाहते हैं, वह उतने कार्यों को चेन-कंपोज करने का एक तरीका है जितना आप लचीले तरीके से चाहते हैं। मैंने इस उद्देश्य के लिए यह मैक्रो लिखा है:

macro_rules! compose {
    ( $last:expr ) => { $last };
    ( $head:expr, $($tail:expr), +) => {
        compose_two($head, compose!($($tail),+))
    };
}

fn compose_two<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
    F: Fn(A) -> B,
    G: Fn(B) -> C,
{
    move |x| g(f(x))
}

fn main() {
    let add = |x| x + 2;
    let multiply = |x| x * 2;
    let divide = |x| x / 2;
    let intermediate = compose!(add, multiply, divide);

    let subtract = |x| x - 2;
    let finally = compose!(intermediate, subtract);

    println!("Result is {}", finally(10));
}

बस finally में संदर्भ जोड़ें और यह काम करेगा:

fn main() {
    let addAndMultiply = compose(|x| x * 2, |x| x + 2);
    let divideAndSubtract = compose(|x| x / 2, |x| x - 2);

    let finally = compose(&*addAndMultiply, &*divideAndSubtract);
    println!("Result is {}", finally(10));
}

Dereferencing addAndMultiply या addAndMultiply एक विशेषता ऑब्जेक्ट को खोल देता है जो addAndMultiply नहीं है; इसे या तो एक Box में लपेटा जाना चाहिए या इसके लिए संदर्भित किया जाना चाहिए ताकि इसे एक समारोह में पारित किया जा सके।





rust