2013-11-14 4 views
13

मैं स्कैला के लिए थोड़ा नया हूं, इसलिए क्षमा करें अगर यह थोड़ा सा मामूली है।एक समझने के लिए लूप समाप्त करना जब आइटम में से किसी एक पर चेक चेक झूठा

मेरे पास ऐसी वस्तुओं की एक सूची है जिसे मैं पुन: प्रयास करना चाहता हूं। मैं प्रत्येक आइटम पर एक चेक निष्पादित करने के लिए और यदि उनमें से केवल एक विफल रहता है तो मैं चाहता हूं कि पूरा कार्य झूठी वापसी करे। तो आप इसे एक और शर्त के रूप में देख सकते हैं। मैं चाहता हूं कि यह आलसी मूल्यांकन किया जाए, यानी जिस क्षण मुझे पहली झूठी वापसी झूठ का सामना करना पड़ेगा।

मुझे for - yield वाक्यविन्यास में उपयोग किया जाता है जो कुछ जनरेटर (वस्तुओं, अनुक्रम इत्यादि की सूची) के माध्यम से उत्पन्न वस्तुओं को फ़िल्टर करता है। मेरे मामले में हालांकि मैं बस लूप को निष्पादित किए बिना तोड़ना और झूठी वापसी करना चाहता हूं। सामान्य जावा में केवल लूप के भीतर return false; होगा।

एक अक्षम रास्ते में (यानी रोक नहीं जब मैं पहली बार झूठी आइटम मुठभेड़), मैं यह कर सकता है:

(for { 
      item <- items 
      if !satisfiesCondition(item) 
     } yield item).isEmpty 

कौन सा अनिवार्य रूप से कह रहा है कि अगर कोई आइटम फिल्टर के माध्यम से इसे बनाने के उन सभी को संतुष्ट शर्त। लेकिन यह थोड़ा उलझन और अक्षम लगता है (मान लें कि आपके पास 1 मिलियन आइटम हैं और पहले व्यक्ति ने शर्त को पूरा नहीं किया है)।

स्कैला में ऐसा करने का सबसे अच्छा और सबसे शानदार तरीका क्या है?

+0

सूची {कोड}? –

+0

जोड़ा गया कोड, धन्यवाद – jbx

+0

क्या आप उन चीज़ों के साथ कुछ भी करने की ज़रूरत है जब आप उन्हें लूप करते हैं? यदि नहीं तो [जिस उत्तर को आप ढूंढ रहे हैं वह यहां है] (http://stackoverflow.com/questions/12547235/scala-forall-example)। –

उत्तर

22

स्केल में forall का उपयोग करके किसी शर्त के लिए पहली झूठी शुरुआत में रोक दिया जाता है। (A related question)

आपका समाधान पुनः:

items.forall(satisfiesCondition) 

कम सर्किटिंग प्रदर्शित करने के लिए:

List(1,2,3,4,5,6).forall { x => println(x); x < 3 } 
1 
2 
3 
res1: Boolean = false 

forall के विपरीत exists जो जैसे ही एक स्थिति उत्पन्न होने पर बंद हो जाता है:

List(1,2,3,4,5,6).exists{ x => println(x); x > 3 } 
1 
2 
3 
4 
res2: Boolean = true 
+0

'forall' और 'exist' समान उपज' के समान नहीं है। यह सिर्फ – Yuriy

+0

@Yury क्षमा करें, आपकी टिप्पणी को समझें, क्या आप स्पष्टीकरण दे सकते हैं? मैंने कभी नहीं कहा कि 'फॉरल' और 'अस्तित्व' 'उपज उपज 'या' के लिए 'जैसा ही है। यदि आप विस्तृत कर सकते हैं तो इससे मदद मिलेगी। –

+0

@ krivachy.akos मौजूद हिस्सा जोड़ने के लिए धन्यवाद। यह लागू करने के लिए बहुत उपयोगी है या, यह जांचने के लिए कि क्या कोई भी आइटम शर्त को पूरा करता है (उन सभी के बजाय)। – jbx

5

स्कैला की समझ के लिए सामान्य पुनरावृत्ति नहीं। इसका मतलब है कि वे हर संभव परिणाम का उत्पादन नहीं कर सकते हैं कि कोई पुनरावृत्ति से उत्पन्न हो सकता है, उदाहरण के लिए, आप जो काम करना चाहते हैं।

तीन चीजें हैं जो समझ के लिए एक स्केल कर सकती हैं, जब आप एक मूल्य लौट रहे हैं (यानी, 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 है, जो अपने सटीक उपयोग के मामले लक्षित करते हैं, हालांकि वे सामान्य समस्या का समाधान नहीं है

  1. उपयोग;
  2. एक गैर-सख्त संग्रह का उपयोग करें; स्कैला का Stream है, लेकिन इसमें ऐसी समस्याएं हैं जो इसके प्रभावी उपयोग को रोकती हैं। Scalaz लाइब्रेरी आपको वहां मदद कर सकती है;
  3. प्रारंभिक वापसी का उपयोग करें, इस प्रकार स्कैला लाइब्रेरी सामान्य समस्या में इस समस्या को हल करती है (विशिष्ट मामलों में, यह बेहतर अनुकूलन का उपयोग करती है)।

तीसरे विकल्प का एक उदाहरण के रूप में, आप इस लिख सकते हैं: के रूप में अच्छी

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) 
} 

:

+0

सभी विवरणों के लिए बहुत बहुत धन्यवाद। मुझे लगता है कि मुझे इसे वापस आना होगा क्योंकि आपने जानकारी का भरपूर धन प्रदान किया है। – jbx

1

forall निश्चित रूप से विशिष्ट परिदृश्य के लिए लेकिन उदाहरण यहाँ अच्छे पुराने प्रत्यावर्तन है के लिए सबसे अच्छा विकल्प है ।

संबंधित मुद्दे