आपके कार्यों के दुष्प्रभाव हैं। उन्हें एक ही इनपुट के साथ दो बार कॉल करना *some-global-var*
के वर्तमान मूल्य के आधार पर अलग-अलग रिटर्न मान दे सकता है। इससे चीजों को परीक्षण करना और कारण बनना मुश्किल हो जाता है, खासतौर पर एक बार जब आप इन वैश्विक वार्सों में से एक से अधिक हो जाते हैं।
लोग अपने कार्यों बुला भी पता नहीं हो सकता है कि आपके कार्यों वैश्विक वर के मूल्य के आधार रहे हैं स्रोत निरीक्षण के बिना,। क्या होगा यदि वे वैश्विक var आरंभ करना भूल जाते हैं? भूलना आसान है। क्या होगा यदि आपके पास इन ग्लोबल वर्र्स पर निर्भर पुस्तकालय का उपयोग करने की कोशिश कर रहे कोड के दो सेट हैं? वे शायद एक दूसरे के ऊपर कदम उठाने जा रहे हैं, जब तक कि आप binding
का उपयोग न करें। जब भी आप रेफरी से डेटा एक्सेस करते हैं तो आप ओवरहेड भी जोड़ते हैं।
आप अपने कोड पक्ष प्रभाव मुक्त लिखते हैं, इन समस्याओं को दूर जाना। एक समारोह अपने आप पर खड़ा है। परीक्षण करना आसान है: इसे कुछ इनपुट पास करें, आउटपुट का निरीक्षण करें, वे हमेशा वही होंगे। यह देखना आसान है कि फ़ंक्शन किस इनपुट पर निर्भर करता है: वे सभी तर्क सूची में हैं। और अब आपका कोड थ्रेड-सुरक्षित है। और शायद तेजी से चलता है।
यदि आप "ऑब्जेक्ट्स/मेमोरी" प्रोग्रामिंग की शैली को "उत्परिवर्तित करने" के लिए उपयोग करते हैं, तो कोड के बारे में सोचना मुश्किल है, लेकिन एक बार जब आप इसे लटकते हैं, तो यह आपके कार्यक्रमों को व्यवस्थित करने के लिए अपेक्षाकृत सरल हो जाता है मार्ग। आपका कोड आम तौर पर उसी कोड के वैश्विक-उत्परिवर्तन संस्करण की तुलना में सरल या सरल के रूप में समाप्त होता है।
(def *address-book* (ref {}))
(defn add [name addr]
(dosync (alter *address-book* assoc name addr)))
(defn report []
(doseq [[name addr] @*address-book*]
(println name ":" addr)))
(defn do-some-stuff []
(add "Brian" "123 Bovine University Blvd.")
(add "Roger" "456 Main St.")
(report))
अलगाव में do-some-stuff
को देखते हुए, यह बिल्ली क्या कर रहा है:
यहाँ एक अत्यधिक काल्पनिक उदाहरण है? बहुत सारी चीजें पूरी तरह से हो रही हैं। इस मार्ग से नीचे स्पेगेटी है। एक यकीनन बेहतर संस्करण:
(defn make-address-book [] {})
(defn add [addr-book name addr]
(assoc addr-book name addr))
(defn report [addr-book]
(doseq [[name addr] addr-book]
(println name ":" addr)))
(defn do-some-stuff []
(let [addr-book (make-address-book)]
(-> addr-book
(add "Brian" "123 Bovine University Blvd.")
(add "Roger" "456 Main St.")
(report))))
अब यह स्पष्ट है क्या do-some-stuff
कर रहा है, यहां तक कि अलगाव में। आप जितनी चाहें उतनी सारी पता पुस्तिकाएं तैर सकते हैं। एकाधिक धागे का अपना स्वयं का हो सकता है। आप इस कोड का उपयोग कई नामस्थानों से सुरक्षित रूप से कर सकते हैं। आप एड्रेस बुक शुरू करना नहीं भूल सकते हैं, क्योंकि आप इसे तर्क के रूप में पास करते हैं। आप आसानी से report
का परीक्षण कर सकते हैं: बस वांछित "नकली" पता पुस्तिका को पास करें और देखें कि यह क्या प्रिंट करता है। आपको किसी भी वैश्विक स्थिति या किसी भी चीज की परवाह नहीं है, लेकिन इस समय आप जिस फ़ंक्शन का परीक्षण कर रहे हैं।
आप एक से अधिक थ्रेड से डेटा संरचना के लिए अद्यतन का समन्वय करने की जरूरत नहीं है, वहां आमतौर पर refs या वैश्विक वार्स उपयोग करने की आवश्यकता है।
मैं आपके द्वारा वर्णित कार्यात्मक दृष्टिकोण के लिए कोई अजनबी नहीं हूं। लेकिन कभी-कभी उस स्थिति के वैश्विक स्थान की सुविधा उपयोगी होती है। सभी कार्यात्मक दृष्टिकोण किनारों पर टूट जाते हैं जो अक्सर देखा जाने वाला मामला आईओ होता है। आप इसे आईओ के एक विशेष मामले पर विचार कर सकते हैं क्योंकि यह सभी धागे के लिए प्रभावी रूप से वैश्विक है। मुझे गलत मत समझो मैं कार्यात्मक दृष्टिकोण पसंद करता हूं और उपरोक्त रेफरी का मेरा उदाहरण उपयोग एक अत्यधिक सरल है इसलिए मैं अधिकांश भाग आपके साथ सहमत हूं। –
सभी कार्यों के मूल्य को निश्चित रूप से एक अच्छा विकल्प पास कर रहा है, लेकिन मुझे लगता है कि कभी-कभी वैश्विक वैरिएबल अधिक से अधिक कार्यों के समूह के मूल्य के गुच्छा को पार करने से कहीं अधिक व्यावहारिक होता है। यह दुष्प्रभावों के लिए स्वाद और सहिष्णुता का विषय है। – ChrisBlom