उच्च क्रम सूची कार्यों के लिए C ++ 11 समर्थन


13

अधिकांश कार्यात्मक प्रोग्रामिंग भाषाओं (जैसे कॉमन लिस्प, योजना / रैकेट, Clojure, हास्केल, स्काला, OCaml, एसएमएल) जैसे सूचियों पर कुछ सामान्य उच्च क्रम काम करता है, समर्थन map, filter, takeWhile, dropWhile, foldl, foldr(देखें उदाहरण के लिए , आम लिस्प, योजना / रैकेट क्लोजर साइड-बाय-साइड संदर्भ पत्र , हास्केल , स्काला , ओकेमेल और एसएमएल प्रलेखन।)

क्या C ++ 11 में सूचियों पर समान मानक विधियाँ या कार्य हैं? उदाहरण के लिए, निम्नलिखित हास्केल स्निपेट पर विचार करें:

let xs = [1, 2, 3, 4, 5]
let ys = map (\x -> x * x) xs

मैं आधुनिक मानक C ++ में दूसरी अभिव्यक्ति कैसे व्यक्त कर सकता हूं?

std::list<int> xs = ... // Initialize the list in some way.
std::list<int> ys = ??? // How to translate the Haskell expression?

उपरोक्त उल्लिखित अन्य उच्च-क्रम के कार्यों के बारे में क्या है?
क्या उन्हें सीधे C ++ में व्यक्त किया जा सकता है?


हां, लेकिन वे दोगुनी लिंक्ड सूची के विशिष्ट कार्यान्वयन से अधिक सामान्य अवधारणाओं पर काम करते हैं। जैसा कि इस क्षेत्र में पायथन का संचालन है। मैं बहुत पसंद करता हूं कि एक विशिष्ट डेटा संरचना से बंधा हुआ हूं। कभी इन ऑपरेशनों को करने की कोशिश की, कहते हैं, Data.Sequenceहास्केल में? यह तुलनात्मक रूप से बदसूरत है।

"यह तुलनात्मक रूप से बदसूरत है।": की तुलना में क्या?
जियोर्जियो

पर एक ही ऑपरेशन की तुलना में [a]। आपको या तो प्रस्तावना फ़ंक्शन को छिपाना होगा, प्रस्तावना के आसपास हैक करना होगा, या एक अलग और कम सहज नाम चुनना होगा।

हो सकता है कि आप सही हों, लेकिन इस सवाल का विषय है कि C ++ में सामान्य सूची के उच्च-क्रम के कार्यों को कैसे व्यक्त किया जाए, हास्केल में Data.Sequence पर अनुरूप कार्यों को कैसे लागू किया जाए।
जियोर्जियो

1
@delnan मैं तर्क दूंगा कि हास्केल अपने दृष्टिकोण में बहुत अधिक सामान्य है। Functor, Foldableऔर Traversableइसे अमूर्त तरीके से प्राप्त कर सकता हूं जैसा कि मैं सोच सकता हूं। Data.Sequenceइन सभी का एक उदाहरण है, तो आप बस कर सकते हैं fmap (\x -> x * x) xsmapहै fmapशुरुआती के लिए विशेष।
एलेक

जवाबों:


16

और भी, C ++ के ऐसे कार्य हैं, एल्गोरिथ्म पर नज़र डालें (या C ++ 11 परिवर्धन के साथ ) हैडर:

std::transform
std::for_each
std::remove_copy_if

इन्हें आसानी से किसी भी कंटेनर के साथ इस्तेमाल किया जा सकता है।

उदाहरण के लिए आपके कोड को इस तरह से व्यक्त किया जा सकता है (आसान कोडिंग के लिए C ++ 11 लैम्ब्डा के साथ):

std::vector<int> x = {1, 2, 3, 4, 5};
std::vector<int> y;
std::transform(x.begin(), x.end(), std::back_inserter(y), [](int elem){ return elem * elem; });

कम सहज ज्ञान युक्त, लेकिन आप आसानी से std::transformकॉल को फ़ंक्शन में लपेट सकते हैं जो नए कंटेनर ( moveबेहतर पूर्णता के लिए शब्दार्थ के साथ ) लौटाएगा ।


धन्यवाद। मैं कुछ दिनों पहले लिखे गए कुछ कोड को सरल बनाना चाहूंगा और यह वास्तव में इसे बहुत छोटा बनाने में मदद कर सकता है। बस एक छोटा सा सवाल: आपको x.begin () और x.end () पास करने की आवश्यकता क्यों है? सिर्फ वेक्टर x पास करने के लिए पर्याप्त नहीं होगा?
जियोर्जियो

std::transformदो पुनरावृत्तियों लेता है, इसलिए, आप एक कंटेनर का एक टुकड़ा ले सकते हैं (याद रखें कि आपके पास पुनरावृत्त अंकगणित हैं)।
mnnhawk

तो आपके पास एक में दो ऑपरेशन हैं: एक टुकड़ा लेना, और एक परिवर्तन लागू करना।
जियोर्जियो

पूर्व में आपके पास दो पुनरावृत्तियाँ हैं और उनके बीच तत्वों में परिवर्तन को लागू करना है। Iterators कार्यात्मक प्रोग्रामिंग में एक आम नहीं है।
mnnhawk

2
मैं इस तरह के पुस्तकालयों से नहीं मिला, सी ++ में इट्रेटर-आधारित एल्गोरिथ्म बहुत उपयोगी है। आप अपने मामले में, std::transformजैसे: का रैपर बना सकते हैं Y<U> map(T<U>, std::function<Y(U)>)
m0nhawk
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.