असाइनमेंट के बिना राज्य बनाए रखना


10

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

एक प्रोग्राम लिखें जो किसी दिए गए डेटा संरचना में परिवर्तन के बारे में घटनाओं को प्राप्त करता है और उन घटनाओं का उत्सर्जन करता है जब यह डेटा संरचना एक निश्चित स्थिति तक पहुंचती है।

इसलिए मेरे पास डेटास्ट्रक्चर की एक प्रति है जिसे मैं बनाए रखता हूं

datastructure_copy::DataStructure 

मेरे पास उन घटनाओं की धारा है जो बदल जाने पर निकाल दी जाती हैं:

datastructure_changes::Stream Change

मेरे पास एक फ़ंक्शन है जो डेटा संरचना में परिवर्तन लागू करता है और एक नई प्रतिलिपि देता है:

apply_change::Change -> DataStructure -> DataStructure

और मेरे पास एक विधेय है जो जांचता है कि क्या डेटा राज्य वांछित स्थिति में पहुंच गया है।

is_ready::DataStructure ->Boolean

दूसरे शब्दों में मुझे धाराओं को काम करने वाले 'कम' की तरह कुछ चाहिए।

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

तो क्या ऐसा करने का एक और तरीका है?

ध्यान दें कि मेरा प्रश्न पूरी तरह से वैचारिक है और मैं हास्केल से गहराई से परिचित नहीं हूं।


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

जवाबों:


2

मुझे पता है कि इसे लागू करने का एक तरीका यह है कि राज्य में हर बार एक बदलाव आने पर इसे फिर से स्थापित किया जाए, हालांकि यह अव्यावहारिक लगता है।

यदि किसी घटना के होने पर लागू होने वाले परिवर्तन एक या दूसरे तरीके से वितरण योग्य नहीं होते हैं, तो आपको हर बार किसी घटना के होने पर राज्य को फिर से स्थापित करना होगा, क्योंकि अंतिम स्थिति प्रारंभिक राज्य के अलावा और कुछ नहीं है, साथ ही क्रमिक परिवर्तन भी हैं। और यहां तक ​​कि अगर परिवर्तन वितरित होते हैं, तो आप आमतौर पर एक राज्य को अगले एक में बदलना चाहते हैं, क्योंकि आप अपनी प्रक्रिया को एक दिए गए राज्य तक पहुंचाने के रूप में तेजी से रोकना चाहते हैं, और चूंकि आपको यह निर्धारित करने के लिए अगले राज्य की गणना करना है कि क्या नया एक वांछित राज्य है।

कार्यात्मक प्रोग्रामिंग में, राज्य परिवर्तन आमतौर पर फ़ंक्शन कॉल और / या फ़ंक्शन मापदंडों द्वारा दर्शाए जाते हैं।

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

तो आपके मामले में, मैं निम्नलिखित कोड द्वारा, स्काला में प्रश्न का उत्तर दूंगा:

import scala.util.Random

val initState = 0.0
def nextState(state: Double, event: Boolean): Double = if(event) state + 0.3 else state - 0.1 // give a new state
def predicate(state: Double) = state >= 1

// random booleans as events
// nb: must be a function in order to force Random.nextBoolean to be called for each  element of the stream
def events(): Stream[Boolean] = Random.nextBoolean #:: events()  

val states: Stream[Double] = initState #:: states.zip(events).map({ case (s,e) => nextState(s,e)}) // a stream of all the successive states

// stop when the state is >= 1 ;
// display all the states computed before it stopped
states takeWhile(! predicate(_)) foreach println 

उदाहरण के लिए, मैं (आउटपुट को सरल कर सकता हूं):

0.0
0.3
0.2
0.5
0.8

val states: Stream[Double] = ... वह रेखा है जहाँ क्रमिक अवस्थाओं की गणना की जाती है।

इस धारा का पहला तत्व प्रणाली की प्रारंभिक स्थिति है। zipतत्वों की जोड़ी की एक धारा में घटनाओं की धारा के साथ राज्यों की धारा को मिलाता है, प्रत्येक जोड़ी एक (राज्य, घटना) है। mapप्रत्येक जोड़ी को नए राज्य होने के एक एकल मान में बदल देता है, जिसे पुराने राज्य के एक समारोह और संबंधित घटना के रूप में गणना की जाती है। एक नया राज्य इसलिए पहले से गणना की गई स्थिति है, साथ ही संबद्ध घटना जो राज्य को "संशोधित" करती है।

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

यदि आप केवल पहले राज्य में रुचि रखते हैं जो विधेय का सम्मान करता है, तो कोड की अंतिम पंक्ति को प्रतिस्थापित करें:

states find predicate get

जो पुनर्प्राप्त करता है:

res7: Double = 1.1

क्या आप उस रेखा के बारे में कुछ जानकारी प्रदान कर सकते हैं जो जादू करती है:val states: Stream[Double]...
बॉबी मारिनॉफ

ज़रूर। कृपया मेरा संपादन देखें।
मुनीमिन

1

आप कहते हैं कि आपके 2 कार्य हैं:

apply_change::Change -> DataStructure -> DataStructure
is_ready::DataStructure ->Boolean

और अगर मैं आपको सही समझता हूं, तो is_readyमहंगा है, इसलिए आप हर बदलाव की घटना के लिए ऐसा नहीं करना चाहते हैं।

आपको जो चाहिए वह है एक फ़ंक्शन एक प्रारंभिक DataStructure लेता है और इसे एक साधारण स्थिति और एक फ़ंक्शन में संघनित करता है जो एक संघनित स्थिति लेता है, एक परिवर्तन और एक नए संघनित राज्य का उत्पादन करता है।

कहो DataStructure एक triplet है x,y,zऔर आप x, y और z के प्राइम नंबर होने का इंतज़ार कर रहे हैं। आपकी संघनित स्थिति तब x का एक सेट हो सकती है, y, z प्रधान नहीं हैं। एक परिवर्तन जो x अभाज्य बनाता है वह x को समुच्चय से हटाता है। एक परिवर्तन जो x को प्रधान नहीं बनाता है x को सेट में जोड़ता है (यदि मौजूद नहीं है)। DataStructure तैयार है तो सेट खाली है।

यह विचार होगा कि संघनित स्थिति को अपडेट करना डेटास्ट्रक्चर को अपडेट करने की तुलना में बहुत सस्ता है और कंप्यूटिंग खरोंच से पहले से ही है।

नोट: एक बेहतर तरीका यह भी हो सकता है कि x, y, z में से किस पर प्राइम होने के लिए जाँच की जाए और यदि वे कहाँ हैं, तो नज़र रखें। प्रत्येक परिवर्तन के लिए आप संबंधित फ़ील्ड को चिह्नित करें जो चेक नहीं किया गया है। तब जब is_ready को कहा जाता है कि आप चेक करें और याद रखें। यह बेहतर है यदि आप प्रत्येक परिवर्तन के बाद is_ready की जाँच नहीं करते हैं क्योंकि x कई बार बदल सकता है और आप केवल एक बार प्राइम की जाँच कर सकते हैं।

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