क्लोजर को अशुद्ध कार्यात्मक शैली माना जाता है?


33

क्या कार्यात्मक प्रोग्रामिंग में क्लोजर को अशुद्ध माना जाता है?

ऐसा लगता है कि आम तौर पर एक समारोह में सीधे मूल्यों को पारित करने से बंद होने से बचा जा सकता है। इसलिए जहां संभव हो, बंद होने से बचा जाना चाहिए?

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

शुद्ध फ़ंक्शन के लिए एक मानदंड यह है कि "फ़ंक्शन हमेशा समान परिणाम मान का मूल्यांकन करता है जिसे समान तर्क मान दिया गया है ।"

मान लीजिए

f: x -> x + y

f(3)हमेशा एक ही परिणाम नहीं देंगे। f(3)के मूल्य पर निर्भर करता है yजिसका कोई तर्क नहीं है f। इस प्रकार fएक शुद्ध कार्य नहीं है।

चूंकि सभी क्लोजर उन मूल्यों पर भरोसा करते हैं जो तर्क नहीं हैं, किसी भी क्लोजर के शुद्ध होने के लिए यह कैसे संभव है? हां, सिद्धांत रूप में बंद मूल्य स्थिर हो सकता है, लेकिन यह जानने का कोई तरीका नहीं है कि केवल फ़ंक्शन के स्रोत कोड को देखकर।

जहाँ यह मुझे इस ओर ले जाता है कि एक ही कार्य एक स्थिति में शुद्ध हो सकता है लेकिन दूसरे में अशुद्ध। कोई हमेशा यह निर्धारित नहीं कर सकता है कि कोई फ़ंक्शन शुद्ध है या उसके स्रोत कोड का अध्ययन करके नहीं। इसके बजाय, किसी को उस बिंदु पर अपने परिवेश के संदर्भ में विचार करना पड़ सकता है, जब इस तरह का भेद किया जा सकता है।

क्या मैं इस बारे में सही ढंग से सोच रहा हूं?


6
मैं हास्केल में हर समय क्लोजर का उपयोग करता हूं, और हास्केल जितना शुद्ध होता है।
थॉमस ईडिंग

5
शुद्ध कार्यात्मक भाषा में, yपरिवर्तित नहीं हो सकता है, इसलिए f(3)इच्छा का आउटपुट हमेशा समान रहेगा।
लिली चुंग

4
yfभले ही यह स्पष्ट रूप से एक इनपुट के रूप में चिह्नित नहीं है , की परिभाषा का हिस्सा है f- यह अभी भी मामला है कि (हम स्पष्ट रूप से निर्भरता बनाने के लिए, हम f_y फ़ंक्शन को निरूपित कर सकते हैं) के fसंदर्भ में परिभाषित किया गया है , और इसलिए परिवर्तन एक अलग फ़ंक्शन देता है । किसी विशेष के लिए परिभाषित विशेष फ़ंक्शन बहुत अधिक शुद्ध है। (उदाहरण के लिए, दो कार्य और अलग - अलग कार्य हैं, और दोनों शुद्ध हैं, भले ही हम उन्हें निरूपित करने के लिए एक ही पत्र का उपयोग करने के लिए हुआ हो।)yyyf_yyf: x -> x + 3f: x -> x + 5
श्रीवत्सआर

जवाबों:


26

पवित्रता को दो चीजों से मापा जा सकता है:

  1. क्या फ़ंक्शन हमेशा समान आउटपुट देता है, समान इनपुट दिया जाता है; यानी यह संदर्भित रूप से पारदर्शी है?
  2. क्या फ़ंक्शन अपने आप से बाहर कुछ भी संशोधित करता है, अर्थात इसके दुष्प्रभाव हैं?

यदि 1 का उत्तर हां है और 2 का उत्तर नहीं है, तो फ़ंक्शन शुद्ध है। क्लोजर केवल एक फ़ंक्शन अशुद्ध करते हैं यदि आप बंद-ओवर चर को संशोधित करते हैं।


क्या पहला आइटम निर्धारक नहीं है? या वह भी पवित्रता का हिस्सा है? मैं प्रोग्रामिंग के संदर्भ में "शुद्धता" की अवधारणा से बहुत परिचित नहीं हूं।

4
@ जिमीहॉफ: जरूरी नहीं। आप किसी फ़ंक्शन में हार्डवेयर टाइमर का आउटपुट डाल सकते हैं, और फ़ंक्शन के बाहर कुछ भी संशोधित नहीं होता है।
रॉबर्ट हार्वे

1
@RobertHarvey क्या यह सब है कि हम किसी फ़ंक्शन के इनपुट कैसे परिभाषित करते हैं? विकिपीडिया से मेरा उद्धरण फ़ंक्शन तर्कों पर केंद्रित है, जबकि आप अतिरिक्त रूप से बंद चर को इनपुट के रूप में मानते हैं।
user2179977

8
@ user2179977: जब तक वे आपस में मेल नहीं खाते, आपको फ़ंक्शन पर अतिरिक्त इनपुट के रूप में बंद चर पर विचार नहीं करना चाहिए । बल्कि, आपको स्वयं को एक फ़ंक्शन होने के लिए, और एक अलग फ़ंक्शन होने पर विचार करना चाहिए जब यह एक अलग मूल्य पर बंद हो जाता है y। इसलिए उदाहरण के लिए हम एक फंक्शन को परिभाषित करते हैं gजो कि g(y)फंक्शन है x -> x + y। फिर gपूर्णांक का एक फ़ंक्शन है जो फ़ंक्शन देता है, पूर्णांक g(3)का एक फ़ंक्शन है जो पूर्णांक लौटाता है, और पूर्णांकों को वापस करने वाले पूर्णांकों g(2)का एक अलग कार्य है। तीनों कार्य शुद्ध हैं।
स्टीव जेसोप Steve ’

1
@ दारोगाग: हाँ। मेरा अपडेट देखें
रॉबर्ट हार्वे

10

क्लोज़र लैंबडा कैलकुलस दिखाई देते हैं, जो कार्यात्मक प्रोग्रामिंग का शुद्धतम रूप है, इसलिए मैं उन्हें "अशुद्ध" नहीं कहूंगा ...

क्लोज़र "अशुद्ध" नहीं हैं क्योंकि कार्यात्मक भाषाओं में कार्य प्रथम श्रेणी के नागरिक हैं - इसका मतलब है कि उन्हें मूल्यों के रूप में माना जा सकता है।

इसकी कल्पना करें (छद्मकोश):

foo(x) {
    let y = x + 1
    ...
}

yएक मूल्य है। यह मूल्य पर निर्भर करता है x, लेकिन xअपरिवर्तनीय है इसलिए yमूल्य भी अपरिवर्तनीय है। हम fooकई बार विभिन्न तर्कों के साथ कॉल कर सकते हैं जो अलग-अलग yएस उत्पन्न करेंगे , लेकिन वे yसभी अलग-अलग दायरे में रहते हैं और अलग-अलग xएस पर निर्भर करते हैं ताकि शुद्धता बरकरार रहे।

अब इसे बदलते हैं:

bar(x) {
    let y(z) = x + z
    ....
}

यहां हम एक क्लोजर का उपयोग कर रहे हैं (हम एक्स पर बंद हो रहे हैं), लेकिन यह सिर्फ एक ही है foo- अलग- barअलग तर्कों के साथ अलग -अलग कॉल अलग-अलग मानों को बनाते हैं y(याद रखें - फ़ंक्शन मान हैं) जो सभी अपरिवर्तनीय हैं, इसलिए शुद्धता बरकरार है।

इसके अलावा, कृपया ध्यान दें कि करीने से करीने से समान प्रभाव पड़ता है:

adder(a)(b) {
    return a + b
}
baz(x) {
    let y = adder(x)
    ...
}

bazवास्तव में से अलग नहीं है bar- दोनों में हम एक फ़ंक्शन मान बनाते हैं जिसका नाम yहै यह तर्क प्लस है x। वास्तव में, लैम्बडा कैलकुलस में आप कई तर्कों के साथ कार्य बनाने के लिए क्लोजर का उपयोग करते हैं - और यह अभी भी अशुद्ध नहीं है।


9

अन्य लोगों ने अपने उत्तरों में सामान्य प्रश्न को अच्छी तरह से कवर किया है, इसलिए मैं केवल आपके संपादन में आपके द्वारा दिए गए भ्रम को साफ करूंगा।

क्लोजर फ़ंक्शन का इनपुट नहीं बनता है, बल्कि यह फ़ंक्शन बॉडी में 'चला जाता है। अधिक ठोस होने के लिए, एक फ़ंक्शन इसके शरीर में बाहरी दायरे में एक मूल्य को संदर्भित करता है।

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

मान लीजिए कि आपके पास इस तरह का एक कोड है:

let make y =
    fun x -> x + y

कॉल करना make 3और make 4आपको दो कार्यों को बंद करने makeका yतर्क देगा। उनमें से एक वापस आ जाएगा x + 3, दूसरा x + 4। वे दो अलग-अलग कार्य हैं, और दोनों ही शुद्ध हैं। वे एक ही makeफ़ंक्शन का उपयोग करके बनाए गए थे , लेकिन यह बात है।

कुछ पैराग्राफ वापस समय के सबसे नोट करें ।

  1. हास्केल में, जो शुद्ध है, आप केवल अपरिवर्तनीय मूल्यों को बंद कर सकते हैं। बंद करने के लिए कोई परस्पर स्थिति नहीं है। आप इस तरह एक शुद्ध कार्य प्राप्त करने के लिए निश्चित हैं।
  2. अशुद्ध कार्यात्मक भाषाओं में, F # की तरह, आप संदर्भ कोशिकाओं और संदर्भ प्रकारों को बंद कर सकते हैं, और प्रभाव में एक अशुद्ध कार्य प्राप्त कर सकते हैं। आप सही हैं कि आपको उस दायरे को ट्रैक करना होगा जिसके भीतर फ़ंक्शन को यह जानने के लिए परिभाषित किया गया है कि यह शुद्ध है या नहीं। आप आसानी से बता सकते हैं कि क्या उन भाषाओं में कोई मूल्य है, इसलिए यह बहुत समस्या नहीं है।
  3. OOP भाषाओं में, जो C # और JavaScript को बंद करने का समर्थन करती हैं, स्थिति कार्यात्मक भाषाओं को नापसंद करने के समान है, लेकिन बाहरी गुंजाइश को ट्रैक करना अधिक मुश्किल हो जाता है क्योंकि चर डिफ़ॉल्ट रूप से परिवर्तनशील होते हैं।

ध्यान दें कि 2 और 3 के लिए, उन भाषाओं में शुद्धता के बारे में कोई गारंटी नहीं है। अशुद्धता वहाँ बंद की संपत्ति नहीं है, लेकिन भाषा की ही है। क्लोजर तस्वीर को अपने आप से ज्यादा नहीं बदलता है।


1
आप हास्केल में उत्परिवर्तित मूल्यों पर पूरी तरह से बंद कर सकते हैं, लेकिन इस तरह की बात को आईओए मोनाद के साथ एनोटेट किया जाएगा।
डैनियल ग्रेज़र

1
@jozefg नहीं, आप एक अपरिवर्तनीय IO Aमूल्य से अधिक बंद करते हैं, और आपका बंद करने का प्रकार IO (B -> C)या सोमेसुच है। पवित्रता बनाए रखी जाती है
केलथ

5

आम तौर पर मैं आपसे "अशुद्ध" की अपनी परिभाषा को स्पष्ट करने के लिए कहूँगा, लेकिन इस मामले में यह वास्तव में मायने नहीं रखता है। यह मानते हुए कि आप इसे पूरी तरह कार्यात्मक शब्द के विपरीत मान रहे हैं , इसका उत्तर "नहीं" है, क्योंकि इसमें बंद होने के बारे में कुछ भी नहीं है जो स्वाभाविक रूप से विनाशकारी है। यदि आपकी भाषा पूरी तरह से बंद किए बिना कार्यात्मक थी, तो यह अभी भी पूरी तरह से बंद होने के साथ कार्यात्मक होगी। यदि इसके बजाय आप "कार्यात्मक नहीं" का मतलब है, जवाब अभी भी "नहीं" है; बंद कार्यों के निर्माण की सुविधा।

ऐसा लगता है कि आम तौर पर किसी फ़ंक्शन को सीधे डेटा पास करके बंद होने से बचा जा सकता है।

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

संपादित करें: अपने स्वयं के संपादन / उदाहरण के संबंध में ...

मान लीजिए

f: x -> x + y

f (3) हमेशा एक ही परिणाम नहीं देगा। f (3) y के मूल्य पर निर्भर करता है जो f का तर्क नहीं है। इस प्रकार च शुद्ध कार्य नहीं है।

निर्भरता यहां शब्द का गलत विकल्प है। आपके द्वारा किए गए बहुत ही विकिपीडिया लेख का हवाला देते हुए:

कंप्यूटर प्रोग्रामिंग में, एक फ़ंक्शन को शुद्ध फ़ंक्शन के रूप में वर्णित किया जा सकता है यदि फ़ंक्शन के बारे में ये दोनों कथन हैं:

  1. फ़ंक्शन हमेशा एक ही परिणाम मान का मूल्यांकन करता है जिसे समान तर्क मान दिया गया है। फ़ंक्शन परिणाम मान किसी भी छिपी जानकारी या स्थिति पर निर्भर नहीं हो सकता है जो प्रोग्राम निष्पादन आय या प्रोग्राम के विभिन्न निष्पादन के बीच बदल सकता है, और न ही यह I / O उपकरणों से किसी भी बाहरी इनपुट पर निर्भर हो सकता है।
  2. परिणाम का मूल्यांकन किसी भी शब्दानुभवनीय दुष्प्रभाव या आउटपुट का कारण नहीं बनता है, जैसे कि उत्परिवर्तनीय वस्तुओं का उत्परिवर्तन या I / O उपकरणों के आउटपुट।

मान yलेना अपरिवर्तनीय है (जो आमतौर पर कार्यात्मक भाषाओं में मामला है), स्थिति 1 संतुष्ट है: सभी मानों के लिए x, मूल्य f(x)नहीं बदलता है। यह इस तथ्य से स्पष्ट होना चाहिए कि yएक स्थिर से अलग नहीं है, और x + 3शुद्ध है। यह भी स्पष्ट है कि कोई उत्परिवर्तन या आई / ओ नहीं चल रहा है।


3

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

अब बात करते हैं क्लोजर की।

बोरिंग (ज्यादातर शुद्ध) "बंद"

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

सादे लैम्ब्डा कैलकुलस में यह तुच्छ की तरह है और पूरी धारणा बस गायब हो जाती है। यह प्रदर्शित करने के लिए, यहाँ एक अपेक्षाकृत हल्का लैम्ब्डा कैलकुलस दुभाषिया है:

-- untyped lambda calculus values are functions
data Value = FunVal (Value -> Value)

-- we write expressions where variables take string-based names, but we'll
-- also just assume that nobody ever shadows names to avoid having to do
-- capture-avoiding substitutions

type Name = String

data Expr
  = Var Name
  | App Expr Expr
  | Abs Name Expr

-- We model the environment as function from strings to values, 
-- notably ignoring any kind of smooth lookup failures
type Env = Name -> Value

-- The empty environment
env0 :: Env
env0 _ = error "Nope!"

-- Augmenting the environment with a value, "closing over" it!
addEnv :: Name -> Value -> Env -> Env
addEnv nm v e nm' | nm' == nm = v
                  | otherwise = e nm

-- And finally the interpreter itself
interp :: Env -> Expr -> Value
interp e (Var name) = e name          -- variable lookup in the env
interp e (App ef ex) =
  let FunVal f = interp e ef
      x        = interp e ex
  in f x                              -- application to lambda terms
interp e (Abs name expr) =
  -- augmentation of a local (lexical) environment
  FunVal (\value -> interp (addEnv name value e) expr)

नोटिस करने के लिए महत्वपूर्ण हिस्सा है addEnvजब हम एक नए नाम के साथ पर्यावरण को बढ़ाते हैं। इस फ़ंक्शन को केवल व्याख्या किए गए Absकर्षण शब्द (लैम्ब्डा शब्द) के "अंदर" कहा जाता है । पर्यावरण "देखा" हो जाता है जब भी हम एक मूल्यांकन Varअवधि और उन Varको रों संकल्प जो कुछ Nameमें निर्दिष्ट Envहै जिसके द्वारा कब्जा कर लिया गया Absयुक्त कर्षण Var

अब, फिर से, सादे LC शब्दों में यह उबाऊ है। इसका मतलब यह है कि बाध्य चर सिर्फ स्थिरांक हैं जहाँ तक किसी को परवाह है। वे सीधे और तुरंत मूल्यांकन करते हैं क्योंकि वे पर्यावरण में निरूपित मानों के रूप में लेक्सिकली उस बिंदु तक पहुंच जाते हैं।

यह भी (लगभग) शुद्ध है। हमारे लैम्ब्डा कैलकुलस में किसी भी शब्द का एकमात्र अर्थ इसके वापसी मूल्य से निर्धारित होता है। एकमात्र अपवाद गैर-समाप्ति का साइड-इफेक्ट है जो ओमेगा शब्द द्वारा सन्निहित है:

-- in simple LC syntax:
--
-- (\x -> (x x)) (\x -> (x x))
omega :: Expr
omega = App (Abs "x" (App (Var "x") 
                          (Var "x")))
            (Abs "x" (App (Var "x") 
                          (Var "x")))

दिलचस्प (अशुद्ध) बंद

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

> function mk_counter() {
  var n = 0;
  return function incr() {
    return n += 1;
  }
}
undefined

> var c = mk_counter()
undefined
> c()
1
> c()
2
> c()
3

यह दर्शाता है कि हमने nआंतरिक फ़ंक्शन में चर पर बंद कर दिया है incrऔर incrउस चर के साथ सार्थक रूप से बातचीत कर रहा है। mk_counterशुद्ध है, लेकिन incrनिश्चित रूप से अशुद्ध है (और संदर्भित पारदर्शी भी नहीं)।

इन दो उदाहरणों के बीच क्या अंतर है?

"परिवर्तनशील" की धारणाएँ

अगर हम देखते हैं कि सादे LC अर्थ में प्रतिस्थापन और अमूर्तता का क्या अर्थ है, तो हम देखते हैं कि वे निश्चित रूप से सादे हैं। चर वास्तव में तत्काल पर्यावरण लुकअप से ज्यादा कुछ नहीं हैं । लैम्ब्डा अमूर्तता का शाब्दिक रूप से आंतरिक अभिव्यक्ति का मूल्यांकन करने के लिए एक संवर्धित वातावरण बनाने से ज्यादा कुछ नहीं है । इस तरह के व्यवहार के लिए इस मॉडल में कोई जगह नहीं है जिसे हमने देखा mk_counter/ incrक्योंकि वहाँ कोई भिन्नता की अनुमति नहीं है।

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

यह नामकरण गणित में "चर" के लंबे ऐतिहासिक उपयोग का अनुसरण करता है, जहां इसका अर्थ "अज्ञात" की तरह कुछ और होता है: (गणितीय) अभिव्यक्ति "x + x" xसमय के साथ अलग-अलग होने की अनुमति नहीं देता है , इसके बजाय इसका अर्थ है (एकल, स्थिर) मान xलेता है।

इस प्रकार, हम "स्लॉट" कहते हैं कि एक स्लॉट में मूल्यों को डालने और उन्हें बाहर निकालने की क्षमता पर जोर दिया जाए।

भ्रम को और जोड़ने के लिए, जावास्क्रिप्ट में ये "स्लॉट्स" वैरिएबल के समान दिखते हैं: हम लिखते हैं

var x;

एक बनाने के लिए और फिर जब हम लिखते हैं

x;

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

-- create a fresh, empty slot and name it `x` in the context of the 
-- expression E
let x = newSlot in E

-- look up the value stored in the named slot named `x`, return that value
get x

-- store a new value, `v`, in the slot named `x`, return the slot
put x v

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

इस अंकन का उपयोग करके हम mk_counterउदाहरण को फिर से लिख सकते हैं (इस बार हास्केल-जैसे सिंटैक्स में, हालांकि निश्चित रूप से संयुक्त राष्ट्र-हास्केल जैसे शब्दार्थ):

mkCounter = 
  let x = newSlot 
  in (\() -> let old = get x 
             in get (put x (old + 1)))

इस मामले में हम ऐसी प्रक्रियाओं का उपयोग कर रहे हैं जो इस परिवर्तनशील स्लॉट में हेरफेर करती हैं। इसे कार्यान्वित करने के लिए हमें न केवल नामों की एक निरंतर वातावरण की आवश्यकता होती है, xबल्कि सभी आवश्यक स्लॉट्स के साथ एक परस्पर वातावरण भी होता है। यह "बंद" लोगों की आम धारणा के करीब है जो लोग बहुत प्यार करते हैं।

फिर, mkCounterबहुत अशुद्ध है। यह भी बहुत संदर्भ से अपारदर्शी है। लेकिन ध्यान दें कि साइड-इफेक्ट नाम पकड़ने या बंद करने से उत्पन्न नहीं होते हैं, बल्कि उत्परिवर्तित सेल के कैप्चर और उस पर साइड-इफ़ेक्टिंग ऑपरेशंस जैसे getऔर put

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

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


1

नहीं, क्लोजर एक फ़ंक्शन को अशुद्ध होने का कारण नहीं बनाते हैं, जब तक कि बंद मूल्य स्थिर नहीं होता है (न तो क्लोजर और न ही अन्य कोड द्वारा बदला जाता है), जो कि कार्यात्मक प्रोग्रामिंग में सामान्य मामला है।

ध्यान दें कि जब आप हमेशा एक तर्क के रूप में एक मूल्य में पारित कर सकते हैं, तो आमतौर पर आप काफी कठिनाई के बिना ऐसा नहीं कर सकते। उदाहरण के लिए (कॉफ़ीस्क्रिप्ट):

closedValue = 42
return (arg) -> console.log "#{closedValue} #{arg}"

आपके सुझाव से, आप अभी लौट सकते हैं:

return (arg, closedValue) -> console.log "#{closedValue} #{arg}"

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

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

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