"ब्लड विरोधाभास" और सी ++


37

मैं यहां लेख पढ़ रहा था: http://www.paulgraham.com/avg.html और "ब्लब विरोधाभास" के बारे में विशेष रूप से दिलचस्प था। जैसा कि कोई है जो मुख्य रूप से सी ++ में कोड करता है, लेकिन अन्य भाषाओं (ज्यादातर हास्केल) के संपर्क में है, मुझे इन भाषाओं में कुछ उपयोगी चीजों के बारे में पता है जो कि सी ++ में दोहराने के लिए कठिन हैं। यह सवाल मुख्य रूप से उन लोगों के लिए है जो सी ++ और कुछ अन्य भाषा दोनों में कुशल हैं, क्या कोई शक्तिशाली भाषा विशेषता या मुहावरा है जिसे आप ऐसी भाषा में उपयोग करते हैं जो केवल सी ++ में लिख रहे थे, पर विचार करना या लागू करना कठिन होगा?

विशेष रूप से इस उद्धरण ने मेरा ध्यान आकर्षित किया:

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

यदि यह पता चलता है कि मैं c ++ का उपयोग करके "ब्लब" प्रोग्रामर के बराबर हूं, तो यह निम्नलिखित प्रश्न उठाता है: क्या आपके पास कोई ऐसी उपयोगी अवधारणा या तकनीक है, जिसका आपने अन्य भाषाओं में सामना किया है, जिसे समझ पाना आपके लिए मुश्किल था। सी ++ में लेखन या "सोच" रहा है?

उदाहरण के लिए प्रोलॉग और मरकरी जैसी भाषाओं में देखे जाने वाले लॉजिक प्रोग्रामिंग प्रतिमान को c ++ में कैस्टर लाइब्रेरी का उपयोग करके लागू किया जा सकता है, लेकिन अंततः मुझे पता चलता है कि मैं प्रोलॉग कोड के संदर्भ में सोच रहा हूं और इसका उपयोग करते समय c ++ समकक्ष में अनुवाद कर रहा हूं। अपने प्रोग्रामिंग ज्ञान को व्यापक बनाने के एक तरीके के रूप में मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या उपयोगी / शक्तिशाली मुहावरों के अन्य समान उदाहरण हैं जो अन्य भाषाओं में अधिक कुशलता से व्यक्त किए जाते हैं कि मैं एक c ++ डेवलपर के रूप में जागरूक नहीं हो सकता हूं। एक और उदाहरण जो दिमाग में आता है वह है लिस्प में मैक्रो सिस्टम, प्रोग्राम के भीतर से प्रोग्राम कोड उत्पन्न करना कुछ समस्याओं के लिए कई फायदे हैं। यह लागू करने के लिए कठिन लगता है और सी + + के बारे में से लगता है।

यह प्रश्न "सी ++ बनाम लिस्प" बहस या किसी भी प्रकार की भाषा-युद्ध प्रकार की बहस का इरादा नहीं है। इस तरह से एक प्रश्न पूछना एकमात्र तरीका है जिससे मैं उन चीजों के बारे में पता लगा सकता हूं जो मुझे नहीं पता कि मुझे नहीं पता है।



2
मैं सहमत हूँ। जब तक यह C ++ बनाम लिस्प बहस में नहीं बदल जाता है मुझे लगता है कि यहां कुछ सीखा जाना है।
jeffythedragonslayer

@MasonWheeler: there are things that other languages can do that Lisp can't- पूरी तरह से, चूंकि लिस्प ट्यूरिंग-पूर्ण है। शायद आपके कहने का मतलब है कि कुछ चीजें हैं जो लिस्प में करने के लिए व्यावहारिक नहीं हैं ? मैं किसी भी प्रोग्रामिंग भाषा के बारे में एक ही बात कह सकता हूं ।
रॉबर्ट हार्वे

2
@ रोबर्टहवे: "ट्यूरिंग समतुल्य होने के अर्थ में सभी भाषाएँ समान रूप से शक्तिशाली हैं, लेकिन यह प्रोग्रामर शब्द की समझ के बारे में नहीं है। (कोई भी ट्यूरिंग मशीन को प्रोग्राम नहीं करना चाहता है।) जिस तरह के पावर प्रोग्रामर की देखभाल नहीं की जा सकती है। औपचारिक रूप से निश्चित, लेकिन यह समझाने का एक तरीका यह होगा कि यह उन विशेषताओं को संदर्भित करता है जो आप केवल कम शक्तिशाली भाषा में प्राप्त कर सकते हैं और इसमें अधिक शक्तिशाली भाषा के लिए दुभाषिया लिख ​​सकते हैं। " - पॉल ग्राहम, प्रश्न में ट्रोलपोस्ट के लिए एक फुटनोट में। (देखें कि मेरा क्या मतलब है?)
मेसन व्हीलर

@ मेसन व्हीलर: (वास्तव में नहीं।)
रॉबर्ट हार्वे

जवाबों:


16

खैर, जब से आपने हास्केल का उल्लेख किया:

  1. पैटर्न मिलान। मुझे लगता है कि पैटर्न पढ़ना और लिखना बहुत आसान है। मानचित्र की परिभाषा पर विचार करें और सोचें कि पैटर्न मिलान के बिना इसे किसी भाषा में कैसे लागू किया जाएगा।

    map :: (a -> b) -> [a] -> [b]
    map f [] = []
    map f (x:xs) = f x : map f xs
  2. प्रकार प्रणाली। यह कभी-कभी दर्द हो सकता है लेकिन यह बेहद मददगार है। आपको इसे वास्तव में समझने के लिए इसके साथ प्रोग्राम करना होगा और यह कितने कीड़े पकड़ता है। इसके अलावा, प्रासंगिक पारदर्शिता अद्भुत है। यह केवल कुछ समय के लिए हास्केल में प्रोग्रामिंग करने के बाद स्पष्ट हो जाता है कि एक अनिवार्य भाषा में राज्य के प्रबंधन के कारण कितने कीड़े हैं।

  3. सामान्य रूप से कार्यात्मक प्रोग्रामिंग। पुनरावृति के बजाय नक्शे और सिलवटों का उपयोग करना। प्रत्यावर्तन। यह उच्च स्तर पर सोचने के बारे में है।

  4. आलसी मूल्यांकन। फिर से यह उच्च स्तर पर सोचने और सिस्टम को मूल्यांकन को संभालने देने के बारे में है।

  5. केबल, पैकेज और मॉड्यूल। मेरे लिए कैबल डाउनलोड पैकेज होने से सोर्स कोड खोजने, मेकफाइल लिखने आदि की तुलना में बहुत अधिक सुविधाजनक है, केवल कुछ नाम आयात करने में सक्षम होने के नाते अनिवार्य रूप से सभी स्रोत फ़ाइलों को एक साथ डंप करने की तुलना में बेहतर है।


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

आप जो कहते हैं वह सच है, लेकिन अभिव्यक्ति की समस्या बीजीय डेटा प्रकारों की सीमाओं के बारे में है (और मानक ओओपी की दोहरी सीमाओं के बारे में)।
ब्लिसॉर्बलेड

@hugomg क्या आपके पास ऑब्जर्वर के बजाय विज़िटर पैटर्न का मतलब था?
सेबेस्टियन रेडल

हाँ। मैं हमेशा उन दो नामों को स्विच करता हूं :)
ह्यूगॉम

@hugomg यह Maybe(C ++ के लिए std::optional) होने के बारे में नहीं है, यह वैकल्पिक / अशक्त / शायद के रूप में स्पष्ट रूप से चीजों को चिह्नित करने के बारे में है।
डिडुप्लिकेटर

7

Memoize!

इसे C ++ में लिखने का प्रयास करें। C ++ 0x के साथ नहीं

बहुत बोझिल? ठीक है, इसे C ++ 0x के साथ आज़माएं ।

देखें कि क्या आप इस 4-लाइन (या 5-लाइन, जो कुछ भी कर सकते हैं: P) D- में संकलन-समय संस्करण:

auto memoize(alias Fn, T...)(T args) {
    auto key = tuple(args);                               //Key is all the args
    static typeof(Fn(args))[typeof(key)] cache;           //Hashtable!
    return key in cache ? cache[key] : (cache[key] = Fn(args));
}

इसे कॉल करने के लिए आपको बस इतना करना चाहिए:

int fib(int n) { return n > 1 ? memoize!(fib)(n - 1) + memoize!(fib)(n - 2) : 1;}
fib(60);

आप स्कीम में भी कुछ इसी तरह की कोशिश कर सकते हैं, हालाँकि यह थोड़ा धीमा है क्योंकि यह रन टाइम पर होता है और क्योंकि यहाँ हैशेड के बजाय लुकअप रैखिक है (और अच्छी तरह से, क्योंकि यह स्कीम है):

(define (memoize f)
    (let ((table (list)))
        (lambda args
            (cdr
                (or (assoc args table)
                    (let ((entry (cons args (apply f args))))
                        (set! table (cons entry table))
                        entry))))))
(define (fib n)
        (if (<= n 1)
            1
            (+ (fib (1- n))
                (fib (- n 2)))))))
(set! fib (memoize fib))

1
तो आप एपीएल से प्यार करते हैं जहां आप एक पंक्ति में कुछ भी लिख सकते हैं? आकार कोई फर्क नहीं पड़ता!
बो पर्सन

@Bo: मैंने APL का उपयोग नहीं किया है। मुझे यकीन नहीं है कि आप "आकार से कोई फर्क नहीं पड़ता" से क्या मतलब है, लेकिन क्या मेरे कोड में कुछ गड़बड़ है जिससे आप ऐसा कहते हैं? और क्या इसका कोई फायदा है कि आप इसे एक अलग भाषा (जैसे C ++) में कैसे करेंगे, जिसके बारे में मुझे जानकारी नहीं है? (मैंने वैरिएबल नामों को थोड़ा संपादित किया, उस स्थिति में जो आप का जिक्र कर रहे थे।)
मेहरदाद

1
@ मेहरदाद - मेरी टिप्पणी सबसे कॉम्पैक्ट प्रोग्राम के बारे में है जो सबसे अच्छी प्रोग्रामिंग भाषा का संकेत नहीं है। उस स्थिति में एपीएल हाथों से जीत जाएगा, क्योंकि आप ज्यादातर चीजें एक ही चार्ट ऑपरेटर के साथ करते हैं। केवल समस्या यह है कि यह अपठनीय है।
बो पर्सन

@ बो: जैसा मैंने कहा, मैं एपीएल की सिफारिश नहीं कर रहा था; मैंने इसे कभी देखा भी नहीं है। आकार एक मानदंड था (हालांकि एक महत्वपूर्ण एक, जैसा कि देखा जा सकता है यदि आप सी ++ के साथ यह कोशिश करते हैं) ... लेकिन क्या इस कोड में कुछ भी गलत है ?
मेहरदाद

1
@ मैट: आपके कोड ने एक फ़ंक्शन को याद किया, लेकिन यह कोड किसी भी फ़ंक्शन को याद कर सकता है । ये वास्तव में बिल्कुल भी समतुल्य नहीं हैं। यदि आप वास्तव में C ++ 0x में इस तरह का एक उच्च-क्रम फ़ंक्शन लिखने की कोशिश करते हैं, तो यह डी की तुलना में बहुत अधिक थकाऊ है (हालांकि यह अभी भी काफी संभव है ... हालांकि यह सी ++ 03 में संभव नहीं है)।
मेहरदाद

5

C ++ एक बहुभाषी भाषा है, जिसका अर्थ है कि यह सोचने के कई तरीकों का समर्थन करने की कोशिश करती है। कभी-कभी C ++ सुविधा अन्य भाषा के कार्यान्वयन की तुलना में अधिक अजीब या कम धाराप्रवाह होती है, जैसा कि कार्यात्मक प्रोग्रामिंग के मामले में है।

उस ने कहा, मैं अपने मूल C ++ भाषा फीचर के शीर्ष के बारे में नहीं सोच सकता जो yieldपायथन या जावास्क्रिप्ट में करता है।

एक अन्य उदाहरण समवर्ती प्रोग्रामिंग है । C ++ 0x में इसके बारे में एक कहावत होगी, लेकिन वर्तमान मानक नहीं है, और संक्षिप्तता सोच का एक नया तरीका है।

इसके अलावा, तेजी से विकास - यहां तक ​​कि शेल प्रोग्रामिंग - कुछ ऐसा है जो आप कभी नहीं सीखेंगे यदि आप सी ++ प्रोग्रामिंग के डोमेन को कभी नहीं छोड़ते हैं।


मैं यह सोचना भी शुरू नहीं कर सकता कि C ++ दिए गए C ++ 2003 में जनरेटर बनाना कितना मुश्किल होगा। C ++ 2011 इसे आसान बना देगा, लेकिन फिर भी यह गैर-तुच्छ है। C ++, C # और Python के साथ नियमित रूप से काम करना, जनरेटर आसानी से आसानी से मेरे द्वारा C ++ (अब C ++ 2011 में लैम्ब्डा को जोड़ा गया है) को सबसे ज्यादा याद रखने की सुविधा है।

मुझे पता है कि मैं इसके लिए गोली मार दूंगा, लेकिन अगर मुझे सी ++ में जनरेटर लागू करना था , तो मुझे इस्तेमाल करना होगा ... setjmpऔर longjmp। मुझे नहीं पता कि कितना टूटता है, लेकिन मुझे लगता है कि अपवाद सबसे पहले होगा। अब, यदि आप मुझे माफ करेंगे, तो मुझे अपने सिर से बाहर निकलने के लिए मॉडर्न सी ++ डिज़ाइन को फिर से पढ़ना होगा ।
माइक डीमोन

@ माइक डीसिमोन, क्या आप इसे (breifly) विस्तृत कर सकते हैं कि आप सेटजम्प और लॉन्गस्पीक के साथ कैसे समाधान करेंगे?

1
कोराउटाइन फंक्शंस के लिए आइसोमॉर्फिक हैं।
GManNickG

1
@Xeo, @Mike: xkcd.com/292
Mehrdad

5

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

आत्मनिरीक्षण और रन-टाइम कोड संकलन / निष्पादन / मूल्यांकन / जो भी बड़े पैमाने पर शक्तिशाली विशेषताएं हैं जो C ++ का अभाव है।


Coroutines FreeRTOS में उपलब्ध हैं ( यहाँ देखें ), जो C. में लागू है। मुझे आश्चर्य है कि उन्हें C ++ में काम करने में क्या लगेगा?
माइक डीमोन

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


1
@Ferruccio: लिंक के लिए धन्यवाद ... विकिपीडिया लेख में भी कुछ हैं। @MSalters: क्या आप सह-दिनचर्या का वर्णन "एक गंदा हैक" के रूप में करते हैं? मेरे लिए एक बहुत ही मनमाना परिप्रेक्ष्य लगता है। पुनरावर्ती एल्गोरिदम द्वारा किए गए स्टोर स्टेट को स्टैक का उपयोग करना - क्या वे हैकिश भी हैं? एफडब्ल्यूआईडब्ल्यू, कोरटाइन और ओओपी एक ही समय (1960 के दशक की शुरुआत) के बारे में आए थे ... कहने के लिए कि पूर्व की सी में वस्तुओं के लिए एक हैक विचित्र लगता है ... मुझे लगता है कि कुछ सी प्रोग्रामर वापस तो वस्तुओं का अनुकरण करने में रुचि रखते थे, > C ++ से 15 साल पहले।
टोनी

4

लिस्प और सी ++ दोनों में एक कंप्यूटर बीजगणित प्रणाली लागू करने के बाद, मैं आपको बता सकता हूं कि लिस्प में कार्य बहुत आसान था, भले ही मैं भाषा के लिए एक पूर्ण नौसिखिया था। सब कुछ सूचीबद्ध होने की यह सरल प्रकृति एक महान कई एल्गोरिदम को सरल बनाती है। दी, C ++ संस्करण कई गुना तेज था। हाँ, मैं लिस्प संस्करण को तेज कर सकता था, लेकिन यह कोड लिस्पी नहीं होगा। स्क्रिप्टिंग एक और चीज है जो हमेशा आसान होने वाली है, उदाहरण के लिए, लिस्प है। यह काम के लिए सही उपकरण का उपयोग करने के बारे में है।


गति में क्या अंतर था?
मात्रा_देव

1
@quant_dev: एक अरब का एक बहु, निश्चित रूप से!
मैट एलेन

मैंने वास्तव में इसे कभी नहीं मापा लेकिन मुझे लगता है कि बड़े ओ अलग थे। मैंने मूल रूप से C ++ संस्करण को एक कार्यात्मक शैली में लिखा था और इसमें गति की समस्याएं भी थीं, जब तक कि मैंने इसे नए, बदले हुए लोगों को बनाने के बजाय डेटा संरचनाओं को संशोधित करने के लिए नहीं सिखाया। लेकिन यह भी कोड को पढ़ने के लिए कठिन बना ...
jeffythedragonslayer

2

जब हम कहते हैं कि एक भाषा "अधिक शक्तिशाली" है तो इसका क्या अर्थ है? जब हम कहते हैं कि एक भाषा "अभिव्यंजक है?" या "अमीर?" मुझे लगता है कि हमारा मतलब है कि एक भाषा को शक्ति प्राप्त होती है, जब उसके क्षेत्र का दृष्टिकोण समस्या का वर्णन करने के लिए इसे आसान और स्वाभाविक बनाने के लिए पर्याप्त होता है - वास्तव में एक राज्य संक्रमण, नहीं? - उस दृश्य के भीतर रहता है। फिर भी वह भाषा काफी कम शक्तिशाली, कम अभिव्यंजक और कम उपयोगी होती है, जब हमारा दृष्टिकोण व्यापक होता है।

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

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

और उच्च-स्तरीय भाषा के बारे में मेरी बाद की समझ, कोडांतरक के साथ मेरे अनुभव के लिए सब कुछ बकाया है। बाद में मैंने जो कुछ सीखा, वह आसान था क्योंकि, आप देखते हैं, सब कुछ - चाहे कितना भी सार हो - अंत में खुद को हार्डवेयर में समायोजित करना चाहिए।

आप अमूर्त के उच्च और उच्च स्तर के बारे में भूलना चाहते हैं - अर्थात्, देखने के संकरा और संकरा क्षेत्र। आप हमेशा बाद में उसे उठा सकते हैं। यह सीखने की बात है, दिनों की बात है। आप मेरी राय से, हार्डवेयर 1 की भाषा सीखने के लिए, हड्डी से जितना दूर हो सकते हैं, बेहतर होगा।


1 शायद काफी मुनासिब नहीं है, लेकिन carऔर cdrहार्डवेयर से उनके नाम ले: पहला लिस्प एक मशीन है कि एक वास्तविक घटते क्रम में रजिस्टर और एक वास्तविक पता रजिस्टर था पर भाग गया। कैसे 'डटकर?


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

"बनाने के लिए सुझाव देना है; परिभाषित करना है नष्ट करना।" यह सोचकर कि आप किसी अन्य भाषा के साथ जीवन को आसान बना सकते हैं अच्छा लगता है, लेकिन एक बार जब आप कूदते हैं, तो आपको नई भाषा के मौसा से निपटना होगा।
माइक डीमोन

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

@ तब आपको नई भाषा के भीतर पिछली भाषा के साथ संवाद करना होगा;)
चाड

2

सहयोगी एरे

डाटा प्रोसेसिंग का एक विशिष्ट तरीका है:

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

इसके लिए सही उपकरण साहचर्य सरणी है

  • एसोसिएटेड सरणियों के लिए सबसे अच्छी भाषा का समर्थन मैंने देखा है MUMPS , जहां साहचर्य सरणियाँ हैं: 1. हमेशा सॉर्ट किया गया 2. वे डिस्क (तथाकथित डेटाबेस) पर, बहुत ही सिंटैक्स के साथ बनाया जा सकता है। (साइड इफेक्ट: यह डेटाबेस के रूप में अत्यधिक शक्तिशाली है, प्रोग्रामर के पास मूल btree तक पहुंच है। अब तक का सर्वश्रेष्ठ NoSQL सिस्टम।)
  • मेरा दूसरा पुरस्कार PHP में जाता है , मुझे फॉर्च्यूनर और आसान सिंटैक्स पसंद है, जैसे $ a [] = x या $ a [x] [y] [z] ++

मुझे वास्तव में जावास्क्रिप्ट के साहचर्य सरणी वाक्यविन्यास पसंद नहीं है, क्योंकि मैं [x] [y] [z] ='s नहीं बना सकता , पहले मुझे एक [x] और [x] [y] बनाना होगा

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

मैं यह नहीं कहता कि C ++ (और जावा) में कोई प्रयोग करने योग्य साहचर्य सरणियाँ नहीं हैं, लेकिन टाइपलेस (या गैर-सख्त टाइप्ड) स्क्रिप्ट भाषाओं को संकलित किया जाता है, क्योंकि वे टाइपलेस स्क्रिप्ट भाषा हैं।

डिस्क्लेमर: मैं C # और अन्य .NET लैंगगेज से परिचित नहीं हूं, AFAIK उनके पास अच्छे ऐररेटिव ऐरे हैंडलिंग है।


1
पूर्ण प्रकटीकरण: MUMPS सभी के लिए नहीं है। उद्धरण: MUMPS यानी हॉरर के एक छोटे से अधिक "वास्तविक दुनिया" उदाहरण देने के लिए, एक भाग शुरू करें अंतर्राष्ट्रीय Obfuscated C कोड प्रतियोगिता, पर्ल का एक डैश, FORTRAN और SNOBOL के दो हीपिंग उपाय, और स्वतंत्र और असम्बद्ध योगदान दर्जनों चिकित्सा शोधकर्ता, और वहां आप जाते हैं।
माइक डीमोन

1
पायथन में, आप या तो अंतर्निहित dictप्रकार का उपयोग कर सकते हैं (उदाहरण के लिए x = {0: 5, 1: "foo", None: 500e3}, ध्यान दें कि कुंजी या मान एक ही प्रकार के होने की कोई आवश्यकता नहीं है)। ऐसा कुछ करने की कोशिश करना a[x][y][z] = 8कठिन है क्योंकि भाषा को भविष्य में यह देखना है कि क्या आप एक मूल्य निर्धारित करने जा रहे हैं या एक और स्तर बना रहे हैं; अपने आप से अभिव्यक्ति a[x][y]आपको नहीं बताती है।
माइक डीमोन

MUMPS मूल रूप से साहचर्य सरणियों के साथ एक मूल-भाषा है (सीधे डिस्क पर संग्रहीत हो सकता है!)। बाद के संस्करणों में प्रक्रियात्मक विस्तार होते हैं, जो इसे मूल PHP के समान बनाता है। बेसिक और पीएचपी का एक डर Mumps को भयावह लगता है, लेकिन दूसरों को नहीं। प्रोग्रामर नहीं। और याद रखें, यह एक बहुत पुरानी प्रणाली है, सभी अजीब चीजें, जैसे एक-अक्षर निर्देश (पूरी तरह से, आप पूर्ण नाम का उपयोग कर सकते हैं), एलआर मूल्यांकन आदेश आदि - साथ ही गैर-अजीब समाधान - केवल एक ही लक्ष्य है: अनुकूलन
रात १२:०१

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

@ माइक: आपके द्वारा पोस्ट किए गए बहुत मनोरंजक लिंक, उन्हें पढ़ते हुए मुझे अच्छी हंसी आई।
शटल87

2

मैं जावा, C \ C ++, असेंबली और जावा स्क्रिप्ट नहीं सीखता। मैं जीवित रहने के लिए C ++ का उपयोग करता हूं।

हालाँकि, मुझे यह कहना होगा कि मुझे असेंबली प्रोग्रामिंग और सी प्रोग्रामिंग अधिक पसंद है। यह ज्यादातर इंपीरियल प्रोग्रामिंग के साथ इनलाइन है।

मुझे पता है कि प्रोग्रामिंग प्रतिमान डेटा प्रकारों को वर्गीकृत करने के लिए महत्वपूर्ण हैं, और शक्तिशाली डिजाइन पेटेंट और कोड के औपचारिककरण की अनुमति देने के लिए उच्च प्रोग्रामिंग अमूर्त अवधारणाएं देते हैं। हालांकि एक अर्थ में, प्रत्येक प्रतिमान एक पैटर्न का संग्रह है और अंतर्निहित हार्डवेयर परत को सार करने के लिए संग्रह है ताकि आपको मशीन के भीतर आंतरिक रूप से EAX या IP के बारे में सोचने की आवश्यकता न हो।

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

दिन के अंत में, सीपीयू क्या है और कंप्यूटर हुड के तहत कैसे काम करता है, इसकी एक अच्छी स्पष्ट मानसिकता और सीमाएं होना बेहतर है। सभी CPU परवाह करता है कि निर्देशों की एक श्रृंखला निष्पादित कर रहा है जो एक रजिस्टर में मेमोरी को अंदर और बाहर स्थानांतरित करता है और एक निर्देश निष्पादित करता है। इसमें डेटा प्रकार, या किसी उच्चतर प्रोग्रामिंग अवधारणाओं की कोई अवधारणा नहीं है। यह केवल डेटा को इधर-उधर करता है।

जब आप प्रोग्रामिंग प्रतिमानों को मिश्रण में जोड़ते हैं तो यह और अधिक जटिल हो जाता है क्योंकि दुनिया के बारे में हमारा दृष्टिकोण बिल्कुल अलग है।


2

क्या कोई ऐसी शक्तिशाली भाषा सुविधा या मुहावरा है जिसका उपयोग आप ऐसी भाषा में करते हैं जो केवल c ++ में लिख रहे थे, तो इसे समझना या लागू करना कठिन होगा?

क्या ऐसी कोई उपयोगी अवधारणा या तकनीक है, जिसका आपने अन्य भाषाओं में सामना किया है, जो आपको सी ++ में "आप" लिख रहे थे या "सोच" रहे थे?

C ++ कई दृष्टिकोणों को अट्रैक्टिव बनाता है। मैं यह कहना चाहूंगा कि यदि आप C ++ में खुद को सीमित करते हैं, तो अधिकांश प्रोग्रामिंग को अवधारणा बनाना मुश्किल है। यहां उन समस्याओं के कुछ उदाहरण दिए गए हैं जो बहुत आसानी से उन तरीकों से हल हो जाते हैं जो C ++ कठिन बनाते हैं।

आवंटन और कॉलिंग सम्मेलनों को पंजीकृत करें

कई लोग C ++ को नंगे धातु के निम्न स्तर की भाषा के रूप में समझते हैं, लेकिन यह वास्तव में नहीं है। मशीन के महत्वपूर्ण विवरणों को दूर करके, C ++ रजिस्टर आवंटन और कॉलिंग कन्वेंशन जैसी व्यावहारिकताओं की अवधारणा को कठिन बनाता है।

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

रन-टाइम कोड जनरेशन

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

मैं एक स्कीम के क्रियान्वयन को पूरा करने और EVALमेटाकार्युलर मूल्यांकन के बारे में जानने के लिए खेल रहा हूं।

पेड़ों से छेड़छाड़

प्रोग्रामिंग में पेड़ हर जगह हैं। पार्सिंग में आपके पास सार सिंटैक्स ट्री हैं। संकलक में आपके पास आईआर हैं जो पेड़ हैं। ग्राफिक्स और जीयूआई प्रोग्रामिंग में आपके पास दृश्य पेड़ हैं।

यह "Ridiculously Simple JSON Parser for C ++" का वजन सिर्फ 484 LOC है जो C ++ के लिए बहुत छोटा है। अब इसकी तुलना अपने सरल JSON पार्सर से करें, जिसका वजन F # के 60 LOC से कम है। अंतर मुख्य रूप से है क्योंकि एमएल बीजीय डेटाैटिप्स और पैटर्न मिलान (सक्रिय पैटर्न सहित) पेड़ों को हेरफेर करने के लिए इसे काफी आसान बनाते हैं।

OCaml में भी लाल-काले पेड़ों की जाँच करें ।

विशुद्ध रूप से कार्यात्मक डेटा संरचनाएं

C ++ में GC की कमी कुछ उपयोगी दृष्टिकोणों को अपनाने के लिए व्यावहारिक रूप से असंभव बना देती है। विशुद्ध रूप से कार्यात्मक डेटा संरचनाएं एक ऐसा उपकरण है।

उदाहरण के लिए, OCaml में इस 47-लाइन रेगुलर एक्सप्रेशन मैचर को देखें। संक्षिप्तता मोटे तौर पर विशुद्ध रूप से कार्यात्मक डेटा संरचनाओं के व्यापक उपयोग के कारण है। विशेष रूप से, कुंजी के साथ शब्दकोशों का उपयोग जो सेट होते हैं। C ++ में ऐसा करना वास्तव में कठिन है क्योंकि stdlib के शब्दकोश और सेट सभी उत्परिवर्तनीय हैं लेकिन आप किसी शब्दकोश की कुंजियों को म्यूट नहीं कर सकते हैं या आप संग्रह को तोड़ सकते हैं।

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

टेल कॉल

न केवल सी ++ टेल कॉल की गारंटी नहीं देता है, बल्कि आरएआई मौलिक रूप से इसके साथ है क्योंकि विनाशकारी पूंछ की स्थिति में कॉल के रास्ते में मिलते हैं। टेल कॉल आपको केवल स्टैक स्थान की एक सीमित मात्रा का उपयोग करके फ़ंक्शन कॉल की एक अनबाउंड संख्या बनाने देता है। यह एक्स्टेंसिबल राज्य मशीनों सहित राज्य मशीनों को लागू करने के लिए बहुत अच्छा है और यह कई अन्यथा अजीब परिस्थितियों में "जेल से मुक्त" कार्ड के लिए एक महान है।

उदाहरण के लिए, वित्त उद्योग से एफ # में संस्मरण के साथ निरंतर-गुजर शैली का उपयोग करके 0-1 नॅप्सैक समस्या के इस कार्यान्वयन की जांच करें । जब आपके पास पूंछ कॉल होती है, तो निरंतरता गुजरती शैली एक स्पष्ट समाधान हो सकती है लेकिन C ++ इसे अव्यवहारिक बनाती है।

संगामिति

एक अन्य स्पष्ट उदाहरण समवर्ती प्रोग्रामिंग है। यद्यपि यह C ++ में पूरी तरह से संभव है, लेकिन यह अन्य उपकरणों की तुलना में बेहद त्रुटि वाला है, विशेष रूप से क्रमिक प्रक्रियाओं को संप्रेषित करता है जैसा कि इरलांग, स्काला और एफ # जैसी भाषाओं में देखा जाता है।


1

यह एक पुराना प्रश्न है, लेकिन चूंकि किसी ने इसका उल्लेख नहीं किया है, मैं सूची (और अब तानाशाही) की समझ जोड़ूंगा। हास्केल या पायथन में एक-लाइनर लिखना आसान है जो फ़िज़-बज़ समस्या को हल करता है। C ++ में ऐसा करने का प्रयास करें।

हालांकि C ++ ने C ++ 11 के साथ आधुनिकता के लिए बड़े पैमाने पर कदम उठाए, लेकिन इसे "आधुनिक" भाषा कहने में थोड़ा खिंचाव है। C ++ 17 (जो अभी तक जारी नहीं किया गया है) आधुनिक मानकों पर आने के लिए अभी तक अधिक कदम उठा रहा है, इसलिए "आधुनिक" का अर्थ "पिछली सहस्राब्दी से नहीं" है।

यहां तक ​​कि सबसे सरल समझें कि एक पायथन में एक पंक्ति में लिख सकता है (और गुइडो की 79 वर्ण रेखा की लंबाई सीमा का पालन करता है) C ++ में अनुवादित होने पर कोड की बहुत सारी और बहुत सारी पंक्तियां बन जाती हैं, और C ++ कोड की उन पंक्तियों में से कुछ पंक्तियों के बजाय जटिल होती हैं।


ध्यान दें: मेरी प्रोग्रामिंग का अधिकांश भाग C ++ में है। मुझे भाषा पसंद है।
डेविड हैमेन

मुझे लगा कि इस प्रस्ताव को हल करना चाहिए था? (C ++ 17 में भी मुझे नहीं लगता है)
मार्टिन बा

2
"आधुनिकता की व्यापक चाल": C ++ 11 में कौन सी "आधुनिक" विशेषताएं हैं जो वर्तमान सहस्राब्दी में आविष्कार की गई थीं?
जियोर्जियो

@MartinBa - "पर्वतमाला" प्रस्ताव की मेरी समझ यह है कि यह पुनरावृत्तियों के लिए एक प्रतिस्थापन है जिसके साथ काम करना आसान है और कम त्रुटि वाले। मैंने कोई सुझाव नहीं देखा है कि वे सूची बोध के रूप में दिलचस्प के रूप में कुछ भी अनुमति दें।
जूल्स

2
@ जिओर्जियो - वर्तमान सहस्राब्दी में किसी भी वर्तमान में लोकप्रिय भाषा का क्या आविष्कार किया गया था?
जूल्स

0

संकलित पुस्तकालय एक कॉलबैक कहलाता है, जो उपयोगकर्ता परिभाषित वर्ग का एक उपयोगकर्ता परिभाषित सदस्य कार्य है।


यह उद्देश्य-सी में संभव है, और यह उपयोगकर्ता इंटरफ़ेस प्रोग्रामिंग को एक हवा बनाता है। आप एक बटन बता सकते हैं: "कृपया, जब आप दबाए जाते हैं तो इस ऑब्जेक्ट के लिए इस विधि को कॉल करें", और बटन ऐसा करेगा। आप कॉलबैक के लिए किसी भी विधि के नाम का उपयोग करने के लिए स्वतंत्र हैं, जो आपको पसंद है, यह लाइब्रेरी कोड में जमे हुए नहीं है, आपको इसके लिए एक एडाप्टर से विरासत में नहीं लेना होगा, न ही संकलक संकलन समय पर कॉल को हल करना चाहता है, और, समान रूप से महत्वपूर्ण, आप एक ही वस्तु के दो अलग-अलग तरीकों को कॉल करने के लिए दो बटन बता सकते हैं।

मैंने अभी तक किसी अन्य भाषा में कॉलबैक को परिभाषित करने के लिए एक समान रूप से लचीला तरीका नहीं देखा है (हालांकि मुझे उनके बारे में सुनने में बहुत दिलचस्पी होगी!)। C ++ में निकटतम समकक्ष संभवतः एक लैंबडा फ़ंक्शन पास कर रहा है जो आवश्यक कॉल करता है, जो फिर से एक टेम्पलेट होने के लिए लाइब्रेरी कोड को प्रतिबंधित करता है।

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

  • C ++ में आप VLA का प्रकार नहीं लिख सकते हैं, न ही इसके लिए पॉइंटर स्टोर कर सकते हैं। यह प्रभावी रूप से गतिशील आकार के सच्चे बहुआयामी सरणियों को प्रतिबंधित करता है (जो C99 के बाद से C में उपलब्ध हैं)।

  • C ++ में आप लैम्बडा के प्रकार को नहीं लिख सकते हैं। आप इसे टाइप भी नहीं कर सकते। इस प्रकार, लैम्बडा के चारों ओर से गुजरने का कोई तरीका नहीं है, या किसी ऑब्जेक्ट में इसके संदर्भ को स्टोर करना है। लैम्ब्डा कार्यों को केवल टेम्प्लेट में ही पास किया जा सकता है।

  • फोरट्रान में आप एक नामीगिस्ट के प्रकार को नहीं लिख सकते हैं। किसी भी तरह की दिनचर्या में एक नामी कलाकार को पास करने का कोई साधन नहीं है। इसलिए, यदि आपके पास एक जटिल एल्गोरिथ्म है जो दो अलग-अलग नामीगैलियों को संभालने में सक्षम होना चाहिए, तो आप भाग्य से बाहर हैं। आप बस एक बार एल्गोरिथ्म नहीं लिख सकते हैं और इसके लिए प्रासंगिक नामसूची पास कर सकते हैं।

ये केवल कुछ उदाहरण हैं, लेकिन आप सामान्य बिंदु देखते हैं: जब भी आप पहली बार इस तरह का प्रतिबंध देखते हैं, तो आप आमतौर पर परवाह नहीं करेंगे क्योंकि यह निषिद्ध काम करने के लिए ऐसा पागल विचार लगता है। हालांकि, जब आप उस भाषा में कुछ बयाना प्रोग्रामिंग करते हैं, तो आप अंततः उस बिंदु पर आते हैं जहां यह सटीक प्रतिबंध एक वास्तविक उपद्रव बन जाता है।


1
I have not seen a similarly flexible way to define a callback in any other language yet (though I'd be very interested to hear about them!) क्या आप सिर्फ ध्वनियों का वर्णन करते हैं जैसे डेल्फी में इवेंट-चालित यूआई कोड काम करता है। (और .NET में WinForms, जो डेल्फी से काफी प्रभावित था।)
मेसन व्हीलर

2
"C ++ में आप VLA का प्रकार नहीं लिख सकते हैं" [...] - C ++ में, C99- शैली के VLAs अनावश्यक हैं, क्योंकि हमारे पास है std::vector। हालांकि स्टैक आवंटन का उपयोग नहीं करने के कारण यह थोड़ा कम कुशल है, यह कार्यात्मक रूप से एक वीएलए के लिए आइसोमोर्फिक है, इसलिए वास्तव में "ब्लब" प्रकार के मुद्दे के रूप में नहीं गिना जाता है: सी ++ प्रोग्रामर यह देख सकते हैं कि यह कैसे काम करता है और बस, "आह हाँ , C, C ++ की तुलना में अधिक कुशलता से करता है।
जूल्स

2
"C ++ में आप लैम्बडा के प्रकार को नहीं लिख सकते। आप इसे टाइप्डिफ भी नहीं कर सकते। इस प्रकार, लैम्बडा के आसपास से गुजरने का कोई तरीका नहीं है, या किसी ऑब्जेक्ट में इसके संदर्भ को स्टोर करें" - यही वह std::functionहै।
जूल्स

3
"मैंने अभी तक किसी अन्य भाषा में कॉलबैक को परिभाषित करने के लिए समान रूप से लचीला तरीका नहीं देखा है (हालांकि मैं उन्हें सुनने के लिए बहुत इच्छुक हूं!) -" जावा में, आप लिख सकते हैं object::methodऔर इसे एक उदाहरण में परिवर्तित किया जाएगा। जो भी इंटरफ़ेस प्राप्त कोड की अपेक्षा करता है। C # के प्रतिनिधि हैं। प्रत्येक वस्तु-कार्यात्मक भाषा में यह विशेषता है क्योंकि यह मूल रूप से दो प्रतिमानों के क्रॉस-सेक्शन का बिंदु है।
जूल्स

@ जूल्स आपकी दलीलें ठीक यही हैं कि ब्लब-विरोधाभास क्या है: एक कुशल C ++ प्रोग्रामर के रूप में, आप इन्हें सीमाओं के रूप में नहीं देखते हैं। हालाँकि, वे सीमाएँ हैं, और C99 जैसी अन्य भाषाएँ इन विशिष्ट बिंदुओं में अधिक शक्तिशाली हैं। आपके अंतिम बिंदु तक: कई भाषाओं में वर्कअराउंड संभव हैं, लेकिन मैं एक को नहीं जानता कि वास्तव में आप किसी भी विधि का नाम किसी अन्य वर्ग को पास कर सकते हैं और इसे किसी ऐसी वस्तु पर कॉल कर सकते हैं जिसे आप प्रदान करते हैं।
cmaster
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.