स्कैला की समझ के लिए सामान्य पुनरावृत्ति नहीं। इसका मतलब है कि वे हर संभव परिणाम का उत्पादन नहीं कर सकते हैं कि कोई पुनरावृत्ति से उत्पन्न हो सकता है, उदाहरण के लिए, आप जो काम करना चाहते हैं।
तीन चीजें हैं जो समझ के लिए एक स्केल कर सकती हैं, जब आप एक मूल्य लौट रहे हैं (यानी, yield
का उपयोग कर रहे हैं)। सबसे बुनियादी मामले में, यह कर सकते हैं:
- प्रकार
M[A]
का एक उद्देश्य है, और एक समारोह A => B
(कि किस प्रकार B
की एक वस्तु देता है जब प्रकार A
की एक वस्तु दी है,) को देखते हुए, एक वापसी M[B]
प्रकार का ऑब्जेक्ट;
उदाहरण के लिए
, वर्ण, Seq[Char]
का एक क्रम को देखते हुए, उस चरित्र के लिए UTF-16 के पूर्णांक प्राप्त करें:
val codes = for (char <- "A String") yield char.toInt
अभिव्यक्ति char.toInt
धर्मान्तरित एक Int
में एक Char
, तो String
- जो है स्काला में Seq[Char]
में अंतर्निहित रूप से परिवर्तित किया गया है, कुछ स्कैला संग्रह जादू के माध्यम से Seq[Int]
(वास्तव में, IndexedSeq[Int]
) बन जाता है।
दूसरी बात यह कर सकते हैं यह है:
प्रकार
M[A]
,
M[B]
,
M[C]
, आदि, और आदि
A
के एक समारोह,
B
,
C
,
D
में की
- को देखते हुए वस्तुओं, प्रकार का ऑब्जेक्ट वापसी
M[D]
;
आप इसे पिछले परिवर्तन के सामान्यीकरण के रूप में सोच सकते हैं, हालांकि पिछले परिवर्तन का समर्थन करने वाली हर चीज में यह परिवर्तन आवश्यक रूप से इस परिवर्तन का समर्थन नहीं कर सकता है। उदाहरण के लिए, हम इस तरह एक battleship खेल के सभी निर्देशांक के लिए निर्देशांक उत्पादन कर सकता है:
val coords = for {
column <- 'A' to 'L'
row <- 1 to 10
} yield s"$column$row"
इस मामले में, हम प्रकार Seq[Char]
और Seq[Int]
, और एक समारोह (Char, Int) => String
की वस्तुओं है, इसलिए हम वापस एक Seq[String]
मिलता है।
तीसरे और अंतिम, समझ कर सकते हैं के लिए बात एक यह है:
- प्रकार
M[A]
का एक उद्देश्य, को देखते हुए इस तरह के उस प्रकार M[T]
किसी भी प्रकार T
के लिए एक शून्य महत्व है, एक समारोह A => B
, और एक शर्त A => Boolean
, स्थिति के आधार पर या तो शून्य या M[B]
टाइप करें।
यह समझना मुश्किल है, हालांकि यह पहले सरल दिख सकता है।
def vowels(s: String) = for {
letter <- s
if Set('a', 'e', 'i', 'o', 'u') contains letter.toLower
} yield letter.toLower
val aStringVowels = vowels("A String")
यह आसान लग रहा है: हम एक शर्त है, हम एक समारोह Char => Char
है, और हम एक परिणाम मिलता है, और वहाँ के कुछ है कि, सरल पहले लग रहा है जैसे कि, वर्णों के क्रम में सभी स्वर खोजने पर नजर डालते हैं किसी भी तरह के "शून्य" की कोई आवश्यकता नहीं प्रतीत होती है। इस मामले में, शून्य खाली अनुक्रम होगा, लेकिन यह शायद ही उल्लेख करने लायक लगता है।
इसे बेहतर समझाने के लिए, मैं Seq
से Option
पर स्विच करूंगा। एक Option[A]
में दो उप-प्रकार हैं: Some[A]
और None
। शून्य, जाहिर है, None
है। इसका उपयोग तब किया जाता है जब आपको मूल्य की संभावित अनुपस्थिति या मूल्य स्वयं का प्रतिनिधित्व करने की आवश्यकता होती है।
अब, मान लें कि हमारे पास एक वेब सर्वर है जहां उपयोगकर्ता लॉग इन हैं और प्रशासकों को प्रशासनिक कार्यों (जैसे वर्डप्रेस करता है) के लिए अपने वेब पृष्ठों पर अतिरिक्त जावास्क्रिप्ट मिलता है। सबसे पहले, हम, उपयोगकर्ता प्राप्त करने की आवश्यकता नहीं है यदि कोई उपयोगकर्ता में लॉग इन, मान लें कि यह इस विधि द्वारा किया जाता है करते हैं:
def getUser(req: HttpRequest): Option[User]
उपयोगकर्ता के लॉग इन नहीं है, तो हम None
मिलता है, अन्यथा हम Some(user)
, जहां मिलता है user
उस डेटा के बारे में जानकारी के साथ डेटा संरचना है जिसने अनुरोध किया था। इसके बाद हम इस तरह के ऑपरेशन को मॉडल कर सकते हैं:
def adminJs(req; HttpRequest): Option[String] = for {
user <- getUser(req)
if user.isAdmin
} yield adminScriptForUser(user)
यहां शून्य के बिंदु को देखना आसान है।जब स्थिति गलत होती है, adminScriptForUser(user)
निष्पादित नहीं किया जा सकता है, इसलिए समझ के लिए कुछ बदले में कुछ चाहिए, और कुछ "शून्य": None
है।
तकनीकी शर्तों में, स्कैला की समझ के लिए monads पर संचालन के लिए सिंटैक्टिक शर्करा प्रदान करता है, जिसमें शून्य के साथ मोनैड के लिए अतिरिक्त ऑपरेशन होता है (उसी लेख में सूची समझें देखें)।
जो आप वास्तव में पूरा करना चाहते हैं उसे catamorphism कहा जाता है, जिसे आमतौर पर fold
विधि के रूप में दर्शाया जाता है, जिसे M[A] => B
के फ़ंक्शन के रूप में माना जा सकता है। आप अनुक्रम में fold
, foldLeft
या foldRight
के साथ इसे लिख सकते हैं, लेकिन उनमें से कोई वास्तव में पुनरावृत्ति को छोटा-सर्किट नहीं करेगा।
शॉर्ट-सर्किटिंग स्वाभाविक रूप से गैर-सख्त मूल्यांकन से उत्पन्न होती है, जो हास्केल में डिफ़ॉल्ट है, जिसमें इनमें से अधिकतर कागजात लिखे गए हैं। स्कैला, अधिकांश अन्य भाषाओं के रूप में, डिफ़ॉल्ट रूप से सख्त है।
आपकी समस्या का समाधान तीन हैं: विशेष तरीकों forall
या exists
है, जो अपने सटीक उपयोग के मामले लक्षित करते हैं, हालांकि वे सामान्य समस्या का समाधान नहीं है
- उपयोग;
- एक गैर-सख्त संग्रह का उपयोग करें; स्कैला का
Stream
है, लेकिन इसमें ऐसी समस्याएं हैं जो इसके प्रभावी उपयोग को रोकती हैं। Scalaz लाइब्रेरी आपको वहां मदद कर सकती है;
- प्रारंभिक वापसी का उपयोग करें, इस प्रकार स्कैला लाइब्रेरी सामान्य समस्या में इस समस्या को हल करती है (विशिष्ट मामलों में, यह बेहतर अनुकूलन का उपयोग करती है)।
तीसरे विकल्प का एक उदाहरण के रूप में, आप इस लिख सकते हैं: के रूप में अच्छी
def hasEven(xs: List[Int]): Boolean = {
for (x <- xs) if (x % 2 == 0) return true
false
}
ध्यान दें कि यह कहा जाता है एक "पाश के लिए", नहीं एक "समझ के लिए", क्योंकि यह 'नहीं करता है टी एक मान वापस नहीं करता है (ठीक है, यह Unit
देता है), क्योंकि इसमें yield
कीवर्ड नहीं है।
आप लेख The Essence of The Iterator Pattern में वास्तविक जेनेरिक पुनरावृत्ति के बारे में और अधिक पढ़ सकते हैं, जो एक ही नाम से पेपर में वर्णित अवधारणाओं के साथ एक स्कैला प्रयोग है। मैं प्रत्यावर्तन छोरों डब्ल्यू/शॉर्ट सर्किट उपयोग के मामलों है कि संग्रह शामिल नहीं है के लिए एक बहुत का उपयोग करते हैं
@tailrec def hasEven(xs: List[Int]): Boolean = xs match {
case head :: tail if head % 2 == 0 => true
case Nil => false
case _ => hasEven(xs.tail)
}
:
सूची {कोड}? –
जोड़ा गया कोड, धन्यवाद – jbx
क्या आप उन चीज़ों के साथ कुछ भी करने की ज़रूरत है जब आप उन्हें लूप करते हैं? यदि नहीं तो [जिस उत्तर को आप ढूंढ रहे हैं वह यहां है] (http://stackoverflow.com/questions/12547235/scala-forall-example)। –