शुद्ध कार्य के लाभ


82

आज मैं शुद्ध कार्य के बारे में पढ़ रहा था, इसके प्रयोग से भ्रमित हो गया:

किसी फ़ंक्शन को शुद्ध कहा जाता है यदि वह उसी सेट के इनपुट के लिए समान मान देता है और इसका कोई भी दुष्प्रभाव नहीं होता है।

उदाहरण के strlen()लिए एक शुद्ध कार्य है, जबकि rand()एक अशुद्ध है।

http://ideone.com/33XJU

उपरोक्त कार्यक्रम उसी तरह से व्यवहार करता है जैसे pureघोषणा के अभाव में ।

फ़ंक्शन को घोषित करने के क्या लाभ हैं pure[अगर आउटपुट में कोई बदलाव नहीं हुआ है]?


7
हां - उत्पन्न विधानसभा को देखें।
फिलिप केंडल

4
मुझे नहीं लगता कि शुद्धता की यह परिभाषा सही है - printfउदाहरण के लिए, इसे अर्हता प्राप्त होगी (एक ही तर्क के साथ दो बार कॉल करने पर समान रिटर्न प्राप्त होता है), लेकिन यह शुद्ध नहीं है।
तदमर्स

14
@ दोस्त: वास्तव में, यह ...and no side-effects...भाग की कमी है ।
Frerich Raabe

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

3
tdammers सही है - ऊपर दी गई शुद्ध की परिभाषा गलत है। शुद्ध का मतलब है कि आउटपुट केवल फ़ंक्शन के इनपुट पर निर्भर करता है; इसके अलावा, कोई भी अवलोकन प्रभाव नहीं होना चाहिए। "एक ही इनपुट के लिए एक ही आउटपुट" उन आवश्यकताओं का एक बहुत ही गलत सारांश है। en.wikipedia.org/wiki/Pure_function
Dancrumb

जवाबों:


145

pure संकलक को पता है कि यह फ़ंक्शन के बारे में कुछ अनुकूलन कर सकता है: जैसे कोड की एक बिट की कल्पना करो

एक शुद्ध कार्य के साथ, संकलक जान सकता है कि उसे fun(10)1000 बार के बजाय केवल एक बार और एक बार मूल्यांकन करने की आवश्यकता है । एक जटिल कार्य के लिए, यह एक बड़ी जीत है।


यानी, आप सुरक्षित रूप से संस्मरण का उपयोग कर सकते हैं
जोएल कोएहॉर्न

@ मब का क्या मतलब है? क्यों नहीं?
कोनराड रुडोल्फ

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

5
@KonradRudolph: 1000 स्ट्रिंग की लंबाई की कल्पना करें। strlenउस पर कॉल करें । तो फिर। एक ही बात हाँ? अब दूसरे वर्ण को संशोधित करें \0। क्या strlenअब भी 1000 वापस आता है? शुरुआती पता समान है (== इनपुट समान है) लेकिन फ़ंक्शन अब एक अलग मान लौटाता है।
माइक बेली

5
@ मब एक अच्छी आपत्ति है, जाहिर है कि आप सही हैं। मुझे इस तथ्य से गुमराह किया गया था कि यहां तक कि पुस्तकों का दावा है कि strlen(जीसीसी / ग्लिबक में) वास्तव में शुद्ध है। लेकिन glibc कार्यान्वयन पर एक नज़र ने इसे गलत दिखाया।
कोनराड रुडोल्फ

34

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

यहाँ GCC प्रलेखनpure विशेषता के बारे में क्या कहता है :

शुद्ध

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

फिलिप का जवाब पहले से ही दिखाता है कि एक फ़ंक्शन जानना 'शुद्ध' है लूप अनुकूलन के साथ मदद कर सकता है।

यहाँ सामान्य उप-अभिव्यक्ति उन्मूलन के लिए एक है (दिया गया fooशुद्ध है):

बन सकता है:


3
मुझे यकीन नहीं है कि अगर कोई ऐसा करता है, लेकिन शुद्ध कार्य भी संकलक को फिर से काम करने की अनुमति देता है जब फ़ंक्शन को कॉल किया जाता है, तो क्या यह रीमेकिंग फायदेमंद होगा। जब साइड इफेक्ट की संभावना होती है, तो संकलक को अधिक रूढ़िवादी होने की आवश्यकता होती है।
mpdonadio

@MPD - हाँ, यह उचित लगता है। और चूंकि एक callनिर्देश सुपरस्क्लेयर सीपीयू के लिए एक अड़चन है, इसलिए कंपाइलर से कुछ मदद मिल सकती है।
अर्जुनशंकर

मैं अस्पष्ट रूप से कई वर्षों पहले एक डीएसपी संकलक का उपयोग करके याद करता हूं जो इस तकनीक का उपयोग रिटर्न मान को जल्द / बाद में प्राप्त करने के लिए करेगा। इससे इसे पाइपलाइन स्टालों को कम करने की अनुमति मिली।
18

1
"Foo (99)" को पहले से ही रखा जा सकता है क्योंकि 99 एक कॉन्स्टेबल है और फू हमेशा एक ही परिणाम देगा? शायद दो-चरण के संकलन में किसी तरह?
निशानवालासन

1
@markwatson - मुझे यकीन नहीं है। ऐसे मामले हो सकते हैं जब यह संभव नहीं है। उदाहरण के लिए यदि fooएक अन्य संकलन इकाई (एक अन्य सी फ़ाइल) का हिस्सा है, या एक पूर्व-संकलित पुस्तकालय में। दोनों मामलों में, कंपाइलर को पता नहीं fooहै कि क्या होता है, और पूर्व-गणना नहीं कर सकता।
अर्जुनशंकर

29

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


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

15

एक गैर-शुद्ध कार्य

एक शुद्ध कार्य के विस्तार की तरह है

जिसमें आपके पास स्पष्ट फ़ंक्शन आर्गुमेंट्स x, y के अलावा, बाकी ब्रह्मांड (या आपके कंप्यूटर से कुछ भी संचार कर सकते हैं) एक निहित संभावित इनपुट के रूप में है। इसी तरह, स्पष्ट पूर्णांक रिटर्न मान के अलावा, आपका कंप्यूटर जो कुछ भी लिख सकता है, वह वापसी मूल्य का अनुमानित हिस्सा है।

यह स्पष्ट होना चाहिए कि गैर-शुद्ध की तुलना में शुद्ध कार्य के बारे में तर्क करना बहुत आसान क्यों है।


1
+1: ब्रह्मांड को एक संभावित इनपुट के रूप में उपयोग करना शुद्ध और नहीं-शुद्ध के बीच के अंतर को समझाने का एक बहुत अच्छा तरीका है।
अर्जुनशंकर

वास्तव में, यह भिक्षुओं के पीछे का विचार है।
क्रिस्टोफर माइकिन्सकी

7

ऐड-ऑन के रूप में, मैं यह उल्लेख करना चाहूंगा कि C ++ 11 कॉन्स्ट्रेक्स कीवर्ड का उपयोग करके कुछ चीजों को संहिताबद्ध करता है। उदाहरण:

कॉन्स्ट्रेक्स के उपयोग पर प्रतिबंध इसे बनाते हैं ताकि फ़ंक्शन काफी शुद्ध हो। इस तरह, संकलक अधिक आक्रामक रूप से अनुकूलन कर सकता है (बस सुनिश्चित करें कि आप पूंछ पुनरावृत्ति का उपयोग करें, कृपया!) और रन समय के बजाय संकलन समय पर फ़ंक्शन का मूल्यांकन करें।

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


4

सामान्य तौर पर, शुद्ध कार्यों में अशुद्ध कार्यों पर 3 फायदे होते हैं, जिनका कंपाइलर फायदा उठा सकता है:

कैशिंग

कहते हैं कि आपके पास शुद्ध कार्य fहै जिसे 100000 बार कहा जा रहा है, क्योंकि यह नियतात्मक है और केवल इसके मापदंडों पर निर्भर करता है, संकलक एक बार इसके मूल्य की गणना कर सकता है और आवश्यक होने पर इसका उपयोग कर सकता है

समानता

शुद्ध कार्य किसी भी साझा की गई मेमोरी को पढ़ना या लिखना नहीं है, और इसलिए बिना किसी अप्रत्याशित परिणाम के अलग थ्रेड में चल सकता है

संदर्भ से गुजर रहा है

किसी फ़ंक्शन f(struct t)को tमान के द्वारा अपना तर्क मिलता है , और दूसरी ओर, कंपाइलर tसंदर्भ के माध्यम से पारित कर सकता है fयदि यह गारंटी देते हुए शुद्ध घोषित किया जाता है कि मूल्य में tपरिवर्तन नहीं होगा और प्रदर्शन लाभ होगा


संकलित समय के विचारों के अलावा, शुद्ध कार्यों का काफी आसान परीक्षण किया जा सकता है: बस उन्हें कॉल करें।

डीबी / फाइल सिस्टम में ऑब्जेक्ट या मॉक कनेक्शन बनाने की कोई आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.