स्टेटफुल लाइब्रेरी के शीर्ष पर साइड इफेक्ट-फ्री इंटरफ़ेस


16

जॉन ह्यूजेस के साथ एक साक्षात्कार में जहां वह एरलंग और हास्केल के बारे में बात करते हैं, उन्होंने एर्लांग में स्टेटफुल लाइब्रेरी का उपयोग करने के बारे में कहा है:

यदि मैं एक स्टेटफुल लाइब्रेरी का उपयोग करना चाहता हूं, तो मैं आमतौर पर इसके ऊपर एक साइड इफेक्ट-फ्री इंटरफ़ेस का निर्माण करता हूं ताकि मैं इसे अपने बाकी कोड में सुरक्षित रूप से उपयोग कर सकूं।

इससे उसका क्या अभिप्राय है? मैं एक उदाहरण के बारे में सोचने की कोशिश कर रहा हूं कि यह कैसा दिखेगा, लेकिन मेरी कल्पना और / या ज्ञान मुझे विफल कर रहा है।


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

जवाबों:


12

(मैं एरलंग को नहीं जानता, और मैं हास्केल नहीं लिख सकता, लेकिन मुझे लगता है कि मैं फिर भी जवाब दे सकता हूं)

खैर, उस साक्षात्कार में एक यादृच्छिक संख्या पीढ़ी पुस्तकालय का उदाहरण दिया गया है। यहाँ एक संभावित स्टेटफुल इंटरफ़ेस है:

# create a new RNG
var rng = RNG(seed)

# every time we call the next(ceil) method, we get a new random number
print rng.next(10)
print rng.next(10)
print rng.next(10)

आउटपुट हो सकता है 5 2 7। अपरिवर्तनीयता पसंद करने वाले व्यक्ति के लिए, यह स्पष्ट गलत है! यह होना चाहिए 5 5 5, क्योंकि हमने उसी वस्तु पर विधि को बुलाया।

तो एक स्टेटलेस इंटरफ़ेस क्या होगा? हम यादृच्छिक संख्याओं के अनुक्रम को एक आलसी मूल्यांकन सूची के रूप में देख सकते हैं, जहां nextवास्तव में सिर को पुनः प्राप्त किया जाता है:

let rng = RNG(seed)
let n : rng = rng in
  print n
  let n : rng = rng in
    print n
    let n : rng in
      print n

इस तरह के एक इंटरफेस के साथ, हम हमेशा पिछली स्थिति में वापस आ सकते हैं। यदि आपके कोड के दो टुकड़े एक ही RNG को संदर्भित करते हैं, तो वे वास्तव में संख्याओं के समान अनुक्रम प्राप्त करेंगे। एक कार्यात्मक मानसिकता में, यह अत्यधिक वांछनीय है।

इसे राज्यभाषा में लागू करना उतना जटिल नहीं है। उदाहरण के लिए:

import scala.util.Random
import scala.collection.immutable.LinearSeq

class StatelessRNG (private val statefulRNG: Random, bound: Int) extends LinearSeq[Int] {
  private lazy val next = (statefulRNG.nextInt(bound), new StatelessRNG(statefulRNG, bound))

  // the rest is just there to satisfy the LinearSeq trait
  override def head = next._1
  override def tail = next._2
  override def isEmpty = false
  override def apply(i: Int): Int = throw new UnsupportedOperationException()
  override def length = throw new UnsupportedOperationException()
}

// print out three nums
val rng = new StatelessRNG(new Random(), 10)
rng.take(3) foreach (n => println(n))

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


1
अपने पहले उदाहरण के रूप में: rnd.next (10) हर बार अलग-अलग मूल्यों का उत्पादन करने के लिए अपरिवर्तनीयता के साथ उतना नहीं करना पड़ता है जितना एक फ़ंक्शन की परिभाषा के साथ करना पड़ता है: फ़ंक्शन 1-टू -1 होना चाहिए। (+1 हालांकि, अच्छा सामान)
स्टीवन एवर्स

धन्यवाद! यह एक बहुत अच्छा, स्पष्ट विवरण और उदाहरण था।
बीटा

1

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

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

काम लिटमस परीक्षण है कि मैं का उपयोग करें:

  • यदि फ़ंक्शन A को फ़ंक्शन B से पहले चलाने की आवश्यकता है, तो A बाहरी स्थिति बनाता है जो B निर्भर करता है।
  • यदि कोई फ़ंक्शन जो मैं लिख रहा हूं उसे याद नहीं किया जा सकता है, तो यह बाहरी परिवर्तनशील स्थिति पर निर्भर करता है। (स्मृति दबाव के कारण संस्मरण एक अच्छा विचार नहीं हो सकता है, लेकिन यह अभी भी संभव होना चाहिए)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.