2012-12-10 19 views
6

मैं library लिख रहा हूं जो श्रेणियों पर मानचित्र/गुना संचालन कर सकता है। मुझे ऑपरेटर के साथ ऐसा करने की ज़रूरत है। मैं कार्यात्मक प्रोग्रामिंग से बहुत परिचित नहीं हूं और मैंने मानचित्र के लिए * और || को फोल्ड के लिए चुना है। तो अंतराल में cos(x) की (जानवर बल एल्गोरिथ्म) अधिकतम लगता है: 8 < x < 9:मानचित्र/फ़ोल्ड ऑपरेटर (सी ++ में)

double maximum = ro::range(8, 9, 0.01) * std::cos || std::max; 

ऊपर में, ro::range किसी भी एसटीएल कंटेनर के साथ बदला जा सकता है।

मैप/फ़ोल्ड ऑपरेटरों के लिए कोई सम्मेलन होने पर मैं अलग नहीं होना चाहता हूं। मेरा सवाल है: क्या कोई गणित नोटेशन है या क्या कोई भाषा मानचित्र/गुना के लिए ऑपरेटरों का उपयोग करती है?

** संपादित करें **

जो लोग पूछा के लिए, नीचे आरओ वर्तमान में क्या कर सकते हैं के छोटे डेमो है। scc छोटी उपयोगिता है जो C++ स्निपेट का मूल्यांकन कर सकती है।

// Can print ranges, container, tuples, etc directly (vint is vector<int>) : 
scc 'vint V{1,2,3}; V' 
{1,2,3} 

// Classic pipe. Alogorithms are from std:: 
scc 'vint{3,1,2,3} | sort | unique | reverse' 
{3, 2, 1} 

// Assign 42 to [2..5) 
scc 'vint V=range(0,9); range(V/2, V/5) = 42; V' 
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9} 


// concatenate vector of strings ('add' is shotcut for std::plus<T>()): 
scc 'vstr V{"aaa", "bb", "cccc"}; V || add' 
aaabbcccc 

// Total length of strings in vector of strings 
scc 'vstr V{"aaa", "bb", "cccc"}; V * size || (_1+_2)' 
9 

// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring : 
scc 'char s[99]; range(s) = "abc"; (range(s) << "XYZ") - "bc"' 
aXYZ 


// Remove non alpha-num characters and convert to upper case 
scc '(range("abc-123, xyz/") | isalnum) * toupper' 
ABC123XYZ 


// Hide phone number: 
scc "str S=\"John Q Public (650)1234567\"; S|isdigit='X'; S" 
John Q Public (XXX)XXXXXXX 
+0

कैसे खाली सीमाओं पर अपने गुना ऑपरेटर काम करेंगे? –

+0

फोल्ड के लिए [केले] नामक एक प्रस्तावित गणित नोटेशन (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125) है। और पर्ल 6 [मेटाएपेटर्स] हैं (http://perl6advent.wordpress.com/2009/12/05/day-5-metaoperator/)। माना जाता है कि दोनों सी ++ के लिए बहुत उपयुक्त नहीं हैं, हालांकि। – phg

+0

@ एनएम - यह वर्तमान में खाली सीमाओं के लिए अपरिभाषित है। लेकिन मैं सिर्फ इस मामले के लिए, फिक्स्चर फिक्स्चर विशेष मूल्य 'blank_value' को जोड़ने के लिए सोच रहा हूं। तो 'add' functor (' std :: plus () के समान) में 'blank_velaue == 0', और' mul == 1' होगा। –

उत्तर

5

मुझे पता है कि भाषाओं में से फोल्डिंग के लिए कोई मानक तरीका नहीं है। स्कैला ऑपरेटरों /: और :\ के साथ-साथ मेटथोड नामों का उपयोग करता है, लिस्प में reduce है, हैस्केल में foldl है।

map दूसरी तरफ मुझे पता है कि सभी भाषाओं में map के रूप में खोजने के लिए और अधिक आम है।

9

यह वास्तव में एक सच्चे उत्तर से अधिक टिप्पणी है, लेकिन टिप्पणी में फिट होना बहुत लंबा है।

कम से कम अगर शब्दावली के लिए मेरी याददाश्त सही ढंग से कार्य करती है, तो नक्शा अनिवार्य रूप से std::transform है, और गुना std::accumulate है। मान लीजिए कि यह सही है, मुझे लगता है कि खुद को लिखने की कोशिश करना सबसे अच्छा सलाह दी जाएगी।

नक्शे का उपयोग आप/शैली अर्थ विज्ञान गुना करना चाहते हैं, तो आप कुछ इस तरह कर सकता है:

std::transform(std::begin(sto), std::end(sto), ::cos); 
double maximum = *std::max_element(std::begin(sto), std::end(sto)); 

हालांकि std::accumulate अधिक एक सामान्य प्रयोजन गुना की तरह है, std::max_element मूल रूप से एक fold(..., max); आप एक ही पसंद करते हैं है ऑपरेशन, आप कुछ ऐसा कर सकते हैं:

double maximum = *(std::max_element(std::begin(sto), std::end(sto), 
    [](double a, double b) { return cos(a) < cos(b); }); 

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

अधिक सामान्य स्तर पर, मैं ऑपरेटरों को अधिभारित करते समय अत्यधिक सावधानी बरतने का आग्रह करता हूं। जब ऑपरेटर ओवरलोडिंग सही ढंग से उपयोग की जाती है - मनमाने ढंग से सटीक पूर्णांक, मैट्रिस, जटिल संख्या इत्यादि जैसी चीजों के लिए ऑपरेटरों को अधिभारित करने में सक्षम होने के कारण, अधिक का उपयोग करके कोड प्रस्तुत करता है बिना अधिभारित ऑपरेटरों के कोड के मुकाबले अधिक पठनीय और समझने योग्य।

दुर्भाग्य से, जब आप अप्रत्याशित तरीके से ऑपरेटरों का उपयोग, ठीक विपरीत सच है - और इन उपयोगों निश्चित रूप से कर रहे हैं अत्यंत अप्रत्याशित - वास्तव में, अच्छी तरह से की "काफी आश्चर्य की बात" श्रेणी में। प्रश्न हो सकते हैं (लेकिन कम से कम थोड़ा सा औचित्य) यदि इन ऑपरेटरों को विशिष्ट क्षेत्रों में अच्छी तरह से समझ में आया, लेकिन सी ++ में अन्य उपयोगों के विपरीत।इस मामले में, हालांकि, आप "पूरे कपड़े से" एक नोटेशन का आविष्कार कर रहे हैं - मुझे किसी भी ऑपरेटर सी ++ का उपयोग करने के बारे में पता नहीं है, या तो फोल्ड या मैप का मतलब है (न ही किसी भी अन्य में समान रूप से समान या समान मार्ग)। संक्षेप में, इस तरह अधिभार का उपयोग करना एक गरीब और अन्यायपूर्ण विचार है।

+0

+1, हालांकि मैं आपके द्वारा किए गए कई बिंदुओं से असहमत हूं। एसटीओ लाइब्रेरी "औद्योगिक ताकत" के विपरीत कुछ है। यह कोडजैम लाइब्रेरी जैसी चीज़ों से पैदा हुआ है और सी -+ वर्बोजिटी को एक-लाइनर में जाम करने की आवश्यकता है (मेरे अन्य - एससीसी परियोजना के लिए)। मानक एसटीएल इंटरफ़ेस का उपयोग करने से अभिव्यक्ति x10 समय कम हो सकती है। बीटीडब्ल्यू, आपका उदाहरण बराबर नहीं है। आपके कोड को श्रेणी के तत्वों को स्टोर करने की आवश्यकता है, और मेरी अभिव्यक्ति कुछ भी संग्रहित नहीं कर रही है। –

+0

@LeonidVolnitsky: वास्तव में नहीं - मैंने जो उदाहरण दिए हैं वे किसी भी उचित तरीके से काम करने वाले इटरेटर्स को स्वीकार करेंगे। हां, वे आमतौर पर एक कंटेनर पर फिर से शुरू होते हैं, लेकिन नहीं, यह वास्तव में एक आवश्यकता नहीं है। –

2

नीचे अर्ध-मानव-पठनीय इंफिक्स सी ++ वाक्यविन्यास में fold का कार्यान्वयन है। ध्यान दें कि कोड बहुत मजबूत नहीं है और केवल बिंदु को प्रदर्शित करने में कार्य करता है। यह अधिक सामान्य 3-तर्क fold ऑपरेटरों (श्रेणी, बाइनरी ऑपरेशन, और तटस्थ तत्व) का समर्थन करने के लिए बनाया जाता है।

यह आसानी से दुरुपयोग के लिए मजेदार तरीका है (क्या आपने अभी "बलात्कार" कहा है?) ऑपरेटर ओवरलोडिंग, और 900 पौंड तोपखाने के खोल के साथ पैर में खुद को शूट करने के सर्वोत्तम तरीकों में से एक है।

enum { fold } fold_t; 

template <typename Op> 
struct fold_intermediate_1 
{ 
    Op op; 
    fold_intermediate_1 (Op op) : op(op) {} 
}; 

template <typename Cont, typename Op, bool> 
struct fold_intermediate_2 
{ 
    const Cont& cont; 
    Op op; 
    fold_intermediate_2 (const Cont& cont, Op op) : cont(cont), op(op) {} 
}; 

template <typename Op> 
fold_intermediate_1<Op> operator/(fold_t, Op op) 
{ 
    return fold_intermediate_1<Op>(op); 
} 

template <typename Cont, typename Op> 
fold_intermediate_2<Cont, Op, true> operator<(const Cont& cont, fold_intermediate_1<Op> f) 
{ 
    return fold_intermediate_2<Cont, Op, true>(cont, f.op); 
} 

template <typename Cont, typename Op, typename Init> 
Init operator< (fold_intermediate_2<Cont, Op, true> f, Init init) 
{ 
    return foldl_func(f.op, init, std::begin(f.cont), std::end(f.cont)); 
} 

template <typename Cont, typename Op> 
fold_intermediate_2<Cont, Op, false> operator>(const Cont& cont, fold_intermediate_1<Op> f) 
{ 
    return fold_intermediate_2<Cont, Op, false>(cont, f.op); 
} 

template <typename Cont, typename Op, typename Init> 
Init operator> (fold_intermediate_2<Cont, Op, false> f, Init init) 
{ 
    return foldr_func(f.op, init, std::begin(f.cont), std::end(f.cont)); 
} 

foldr_func और foldl_func (बाएँ और दाएँ परतों की वास्तविक एल्गोरिदम) कहीं परिभाषित कर रहे हैं।

इस तरह का प्रयोग करें यह:

foo myfunc(foo, foo); 
container<foo> cont; 
foo zero, acc; 

acc = cont >fold/myfunc> zero; // right fold 
acc = cont <fold/myfunc< zero; // left fold 

शब्द fold गरीब आदमी का नया आरक्षित शब्द का एक प्रकार यहाँ के रूप में प्रयोग किया जाता है। एक इस वाक्य रचना के कई रूप परिभाषित कर सकते हैं, भीतरी ऑपरेटर बाहरी एक (रों) के रूप में ही या अधिक से अधिक पूर्वता होना आवश्यक सहित

<<fold/myfunc<< >>fold/myfunc>> 
<foldl/myfunc> <foldr/myfunc> 
|fold<myfunc| |fold>myfunc| 

। यह सी ++ व्याकरण की सीमा है।

map के लिए, केवल एक मध्यवर्ती की आवश्यकता है और वाक्यविन्यास उदाहरण हो सकता है

mapped = cont |map| myfunc; 

इसे कार्यान्वित करना एक साधारण अभ्यास है।

ओह, और उत्पादन में इस वाक्य का इस्तेमाल करें नहीं है, जब तक आप जानते हैं कि बहुत अच्छी तरह से तुम क्या कर रहे है, और शायद भले ही आप कर;)

+0

+1। एसटीओ की तुलना में यह अधिक असामान्य है। –