2011-12-30 10 views
10

संभव डुप्लिकेट:
Functional programming and non-functional programmingक्या कोई व्यक्ति आम आदमी शब्दों में व्याख्या कर सकता है कि एक कार्यात्मक भाषा क्या है?

मुझे डर है कि विकिपीडिया मुझे किसी भी आगे नहीं लाए हूँ। बहुत धन्यवाद

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

Functional programming and non-functional programming

+1

बस साफ़ करने के लिए। * विकीपा लेख * लगभग * कार्यात्मक प्रोग्रामिंग * बहुत स्पष्ट और चालाक हैं। यदि आप उनका पालन नहीं करते हैं तो यह स्पष्ट है कि आप एक नौसिखिया हैं और मुझे नहीं लगता कि आप * फंक्शनल प्रोग्रामिंग * के बारे में मेरे उत्तर में जो कुछ भी चाहते थे उसका पालन कर सकते हैं। मैंने सोचा कि मुझे अपने जवाब में केवल कुछ पंक्तियां लिखनी चाहिए थीं। उस स्थिति में, आपको इसके बारे में बुनियादी सीखकर शुरू करना होगा। – Lion

+0

जब आप मूल बातें हैं, तो आप वास्तव में क्या मतलब है? मैंने सोचा कि विभिन्न प्रतिमानों के बारे में सीखना मूल बातें थी .. – Schnappi

उत्तर

11

सबसे पहले जानने के क्या एक Turing machine है (विकिपीडिया से)।

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

यह लगभग Lamda calculus. (विकिपीडिया से) है।

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

कार्यात्मक प्रोग्रामिंग भाषाओं, गणना के अपने मौलिक मॉडल, लैम्ब्डा पथरी के रूप में, का उपयोग करते हुए सभी अन्य प्रोग्रामिंग भाषाओं गणना के अपने मौलिक मॉडल के रूप में ट्यूरिंग मशीन का उपयोग करें। (ठीक है, तकनीकी रूप से, मुझे कार्यात्मक प्रोग्रामिंग भाषाएं vr.s imperative programming भाषाएं कहनी चाहिए- क्योंकि अन्य प्रतिमानों में भाषाएं अन्य मॉडल का उपयोग करती हैं। उदाहरण के लिए, एसक्यूएल रिलेशनल मॉडल का उपयोग करता है, प्रोलॉग एक तर्क मॉडल का उपयोग करता है, और इसी तरह। हालांकि, बहुत कुछ भाषाई भाषाओं पर चर्चा करते समय भाषाएं वास्तव में सोचती हैं या तो कार्यात्मक या अनिवार्य हैं, इसलिए मैं आसान सामान्यता के साथ रहूंगा।)

मेरा मतलब "गणना के मौलिक मॉडल" से क्या है? खैर, सभी भाषाओं को दो परतों में सोचा जा सकता है: एक, कुछ कोर ट्यूरिंग-पूर्ण भाषा, और उसके बाद या तो अबास्ट्रक्शन या सिंटैक्टिक चीनी की परतें (आप उन्हें पसंद करते हैं या नहीं) के आधार पर आधार ट्यूरिंग- पूरी भाषा अनिवार्य भाषाओं के लिए मूल भाषा गणना के क्लासिक ट्यूरिंग मशीन मॉडल का एक रूप है, जिसे "सी भाषा" कहा जा सकता है। इस भाषा में, स्मृति बाइट्स की एक सरणी है जिसे पढ़ा और लिखा जा सकता है, और आपके पास एक या अधिक CPUs हैं जो स्मृति पढ़ते हैं, सरल अंकगणित, परिस्थितियों पर शाखा करते हैं, आदि। इन भाषाओं की गणना के मौलिक मॉडल से मेरा मतलब यह है कि ट्यूरिंग मशीन है।

कार्यात्मक भाषाओं के लिए गणना का मौलिक मॉडल लैम्ब्डा कैलकुलस है, और यह दो अलग-अलग तरीकों से दिखाई देता है। पहले, एक बात यह है कि कई कार्यात्मक भाषाएं भाषा में लिखे गए कार्यक्रम के व्यवहार को निर्दिष्ट करने के लिए लैम्बडा कैलकुस के अनुवाद के संदर्भ में स्पष्ट रूप से अपने विनिर्देशों को लिखना है (इसे "denotational semantics" के रूप में जाना जाता है)।और दूसरा, लगभग सभी कार्यात्मक प्रोग्रामिंग भाषाएं उनके कंपाइलरों को एक स्पष्ट लैम्ब्डा-कैलकुस-जैसी इंटरमीडिएट भाषा का उपयोग करने के लिए लागू करती हैं- Haskell में कोर, Lisp है और योजना में उनके "desugared" प्रतिनिधित्व (सभी मैक्रोज़ लागू होने के बाद) है, Ocaml (Objective Categorical Abstract Machine Language) है लिस्पीश मध्यवर्ती प्रतिनिधित्व, और इसी तरह।

तो यह लैम्ब्डा कैलकुस क्या है जिसके बारे में मैं जा रहा हूं? खैर, मूल विचार यह है कि, किसी भी गणना करने के लिए, आपको केवल दो चीजों की आवश्यकता है। आपको जिस चीज की आवश्यकता है वह अबाउटक्शन है- एक अनाम, एकल-तर्क, फ़ंक्शन की परिभाषा। लम्बाडा कैलकुस को पहली बार परिभाषित करने वाले एलोनोजो चर्च ने फ़ंक्शन को परिभाषित करने के लिए एक अस्पष्ट अक्षर लैम्बडा के रूप में परिभाषित करने के लिए अस्पष्ट नोटेशन का उपयोग किया, उसके बाद कार्य के लिए तर्क के एक-चरित्र नाम के बाद, एक अवधि के बाद, अभिव्यक्ति के बाद समारोह का शरीर तो पहचान फ़ंक्शन, जिसने कोई मान दिया है, बस उस मान को वापस कर देता है, "λx.x" जैसा दिखता है, मैं थोड़ा और मानव-पठनीय दृष्टिकोण का उपयोग करने जा रहा हूं- मैं λ चरित्र को शब्द " मज़ा ", अवधि" -> "के साथ, और सफेद स्थान की अनुमति दें और बहु-चरित्र नामों को अनुमति दें। इसलिए मैं पहचान फ़ंक्शन को "मजेदार एक्स -> एक्स" के रूप में लिख सकता हूं, या यहां तक ​​कि "मजेदार जो कुछ भी -> जो भी हो"। नोटेशन में परिवर्तन मौलिक प्रकृति को नहीं बदलता है। ध्यान दें कि यह हास्केल और लिस्प-अभिव्यक्ति जैसी भाषाओं में "लैम्ब्डा अभिव्यक्ति" नाम का स्रोत है जो अज्ञात स्थानीय कार्यों को पेश करता है।

लैम्ब्डा कैलकुस में आप केवल एक ही चीज कर सकते हैं, कार्यों को कॉल करना है। आप इसे एक तर्क लागू करके एक समारोह कहते हैं। मैं मानक सम्मेलन का पालन करने जा रहा हूं कि आवेदन पंक्ति में केवल दो नाम हैं- इसलिए f x एफ नामक फ़ंक्शन पर x मान लागू कर रहा है। यदि हम चाहते हैं कि हम लैम्ब्डा अभिव्यक्ति समेत किसी अन्य अभिव्यक्ति के साथ एफ को प्रतिस्थापित कर सकते हैं- और जब हम अभिव्यक्ति के लिए तर्क लागू करते हैं, तो आप एप्लिकेशन को फ़ंक्शन के बॉडी के साथ प्रतिस्थापित कर सकते हैं, तर्क नाम की सभी घटनाओं के साथ जो भी मूल्य लागू किया गया था। तो अभिव्यक्ति (fun x -> x x) yy y बन जाती है।

सैद्धांतिक चिकित्सकों ने "मूल्य के साथ परिवर्तनीय की सभी घटनाओं को प्रतिस्थापित करके" का अर्थ सटीक रूप से परिभाषित करने के लिए बहुत लंबा समय तय किया है, और यह कितना सटीक काम करता है (अल्फा जैसे शब्दों को फेंकना) नामकरण "), लेकिन अंत में चीजें ठीक उसी तरह काम करती हैं जैसे आप उन्हें उम्मीद करते हैं। अभिव्यक्ति (fun x -> x x) (x y)(x y) (x y) बन जाती है - अज्ञात फ़ंक्शन के भीतर x तर्क और लागू होने वाले x के बीच कोई भ्रम नहीं है। यह कई स्तरों पर भी काम करता है- अभिव्यक्ति (fun x -> (fun x -> x x)) (x x)) (x y) पहले (fun x -> x x) ((x y) (x y)) और फिर ((x y) (x y)) ((x y) (x y)) बन जाती है। अंतर्निहित फ़ंक्शन में x (“(fun x -> x x)”) अन्य x की तुलना में एक अलग एक्स है।

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

एक तरफ, मैं उन चीजों को जोड़ दूंगा जहां चीजों को असंबद्ध करने की आवश्यकता होती है, और जहां उन्हें आवश्यकता नहीं होती है उन्हें भी बढ़ाएं। उनका एकमात्र अंतर समूहबद्ध है, उनके पास कोई अन्य अर्थ नहीं है।

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

सबसे पहले, मैंने निर्दिष्ट किया कि एक फ़ंक्शन ने केवल एक तर्क लिया- आपके पास एक ऐसा कार्य कैसे है जिसमें दो या अधिक, तर्क लगते हैं? आसान- आपके पास एक ऐसा फ़ंक्शन है जो एक तर्क लेता है, और एक फ़ंक्शन देता है जो दूसरा तर्क लेता है।उदाहरण के लिए, फ़ंक्शन संरचना को fun f -> (fun g -> (fun x -> f (g x))) के रूप में परिभाषित किया जा सकता है - एक फ़ंक्शन के रूप में जो एक तर्क f लेता है, और एक फ़ंक्शन देता है जो तर्क g लेता है और एक फ़ंक्शन देता है जो एक तर्क x लेता है और f f (g x) देता है।

तो हम केवल फ़ंक्शंस और एप्लिकेशन का उपयोग करके पूर्णांक का प्रतिनिधित्व कैसे करते हैं? आसानी से (यदि स्पष्ट रूप से नहीं है) - उदाहरण के लिए, संख्या एक, fun s -> fun z -> s z है - एक "उत्तराधिकारी" फ़ंक्शन और "शून्य" जेड दिया गया है, तो एक शून्य के उत्तराधिकारी है। दो मजेदार है ->fun z -> s s z, उत्तराधिकारी के उत्तराधिकारी उत्तराधिकारी, तीन fun s -> fun z -> s s s z है, और इसी तरह।

दो संख्याओं को जोड़ने के लिए, x और y कहें, सूक्ष्म होने पर फिर से सरल है। अतिरिक्त कार्य सिर्फ fun x -> fun y -> fun s -> fun z -> x s (y s z) है। यह अजीब लग रहा है, इसलिए मुझे यह दिखाने के लिए एक उदाहरण के माध्यम से चलाने दें कि वास्तव में काम करते हैं- चलिए संख्या 3 और 2 जोड़ते हैं। अब, तीन सिर्फ (fun s -> fun z -> s s s z) है और दो केवल (fun s -> fun z -> s s z) है, इसलिए हमें मिलता है (प्रत्येक चरण लागू होता है एक समारोह के लिए एक तर्क, कोई विशेष क्रम में):

(fun x -> fun y -> fun s -> fun z -> x s (y s z)) (fun s -> fun z -> s s s z) (fun s -> fun z -> s s z) 

(fun y -> fun s -> fun z -> (fun s -> fun z -> s s s z) s (y s z)) (fun s -> fun z -> s s z) 

(fun y -> fun s -> fun z -> (fun z -> s s s z) (y s z)) (fun s -> fun z -> s s z) 

(fun y -> fun s -> fun z -> s s s (y s z)) (fun s -> fun z -> s s z) 

(fun s -> fun z -> s s s ((fun s -> fun z -> s s z) s z)) 

(fun s -> fun z -> s s s (fun z -> s s z) z) 

(fun s -> fun z -> s s s s s z) 

और अंत में हम शून्य करने के लिए उत्तराधिकारी है, और अधिक बोलचाल की भाषा में पाँच के रूप में जाना के लिए उत्तराधिकारी के उत्तराधिकारी के लिए उत्तराधिकारी के उत्तराधिकारी की unsurprising जवाब मिल ।

(fun x -> fun y -> fun s -> fun z -> x (y s) z) 

मैं करने के लिए इसे छोड़ देंगे: इसके अलावा y value- साथ x मूल्य की zero की जगह (या जहां हम गिनती शुरू) गुणन को परिभाषित करने के द्वारा काम करता है, लेकिन इसके बदले हम "उत्तराधिकारी" की अवधारणा के साथ लुढ़का आप ऊपर कोड

Wikipedia says

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

// Fibonacci numbers, imperative style 
int fibonacci(int iterations) 
{ 
    int first = 0, second = 1; // seed values 

    for (int i = 0; i < iterations; ++i) { 
     int sum = first + second; 
     first = second; 
     second = sum; 
    } 

    return first; 
} 

std::cout << fibonacci(10) << "\n"; 

एक कार्यात्मक संस्करण (Haskell में) यह करने के लिए एक अलग लग रहा है:

-- Fibonacci numbers, functional style 

-- describe an infinite list based on the recurrence relation for Fibonacci numbers 
fibRecurrence first second = first : fibRecurrence second (first + second) 

-- describe fibonacci list as fibRecurrence with initial values 0 and 1 
fibonacci = fibRecurrence 0 1 

-- describe action to print the 10th element of the fibonacci list 
main = print (fibonacci !! 10) 

See this PDF also

+0

आपका उत्तर मेरा, +1 और मेरा हटा दिया गया है। – orlp

+0

से आपको उत्कृष्ट स्पष्टीकरण, मुझे लगता है कि मुझे यह घोषणात्मक बनाम प्रक्रियात्मक भेदभाव ऑब्जेक्ट उन्मुख प्रोग्रामिंग इस तस्वीर में कैसे फिट करता है? – Schnappi

+0

इसे देखें। http://answers.google.com/answers/threadview?id=207071 – Lion

4

(ए) कार्यात्मक प्रोग्रामिंग यंत्रवत् समाधान वर्णन करता है। आप एक मशीन को परिभाषित करते हैं जो लगातार सही ढंग से आउटपुट कर रही है, उदा। Caml साथ:

let rec factorial = function 
    | 0 -> 1 
    | n -> n * factorial(n - 1);; 

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

int factorial(int n) { 
    int result = 1; 
    while (n > 0) { 
    result *= n--; 
    } 
    return result; 
} 

एक कार्यात्मक प्रोग्रामिंग भाषा आप (ए) हर समय करना चाहती है। मेरे लिए, पूरी तरह से कार्यात्मक प्रोग्रामिंग की सबसे बड़ी मूर्तता विशिष्टता स्टेटलेसनेस है: आप कभी भी उन चीज़ों के स्वतंत्र रूप से घोषित नहीं करते हैं जिनका उपयोग उनके लिए किया जाता है।

+2

बस साफ़ करने के लिए। मैंने आपकी पोस्ट पर कोई वोट नहीं डाला। न तो ऊपर और न ही नीचे। – Lion

संबंधित मुद्दे

 संबंधित मुद्दे