2014-11-01 7 views
5

मैं स्काला में comprehensions के लिए समझने की कोशिश कर रहा हूँ, और मुझे लगता है कि मैं इन सबसे छुटकारा समझ में उदाहरण के लिए बहुत कुछ है ...स्काला() बनाम के लिए {}

एक बात मैं एक मुश्किल समय हो रही है figuring बाहर() बनाम {} के लिए है। मैंने दोनों की कोशिश की है, और ऐसा लगता है जैसे मैं एक चीज एक में कर सकता हूं लेकिन यह दूसरे में टूट जाता है।

उदाहरण के लिए, इस काम नहीं करता है:

def encode(number: String): Set[List[String]] = 
    if (number.isEmpty) Set(List()) 
    else { 
    for (
     split <- 1 to number.length 
     word <- wordsForNum(number take split) 
     rest <- encode(number drop split) 
    ) yield word :: rest 
    }.toSet 

हालांकि, अगर आप इसमें {बदलने}, यह संकलन करता है:

def encode(number: String): Set[List[String]] = 
    if (number.isEmpty) Set(List()) 
    else { 
    for { 
     split <- 1 to number.length 
     word <- wordsForNum(number take split) 
     rest <- encode(number drop split) 
    } yield word :: rest 
    }.toSet         

ये उदाहरण एक Coursera वर्ग मैं से हैं ले रहा। प्रोफेसर ने वीडियो & में "क्यों" का उल्लेख नहीं किया था, मैं सोच रहा था कि कोई और जानता है या नहीं।

धन्यवाद!

+0

धन्यवाद - मैं कई बनाम एकल लाइन उदाहरण के साथ के लिए {} की जरूरत कनेक्ट नहीं था कि मैं के माध्यम से काम कर रहा था। – anonygrits

उत्तर

7

कल्पना में वाक्य रचना से है, यह लग सकता है कि कोष्ठक और ब्रेसिज़ परस्पर विनिमय कर रहे:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#for-comprehensions-and-for-loops

लेकिन क्योंकि जनरेटर सेमीफाइनल से अलग होते हैं, निम्नलिखित नियमों में लात :

http://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html#newline-characters

मैंने पढ़ा है और अतीत में उस अनुभाग, जिसमें से मैं थोड़ा सार है कि नई-पंक्तियों ब्रेसिज़ में सक्षम होते हैं, जो कहने के लिए है याद को समझ लिया है , एक न्यूलाइन चार को nl के रूप में लिया जाता है जो semi के रूप में कार्य करता है।

तो आप जनरेटर को अर्धविरामों का उपयोग करने के बजाय अलग-अलग लाइनों पर रख सकते हैं।

यह सामान्य "अर्धविराम अनुमान" है जो आपको अर्धविरामों को कथन टर्मिनेटर के रूप में नहीं लिखने देता है। तो जनरेटर के बीच में नई पंक्ति नहीं, एक अर्द्ध के रूप में लिया जाता है, उदाहरण के लिए: वास्तव में पूरी तरह से जवाब के लिए

scala> for (c <- 
    | List(1,2,3) 
    |) yield c+1 
res0: List[Int] = List(2, 3, 4) 

scala> for { c <- 
    | List(1,2,3) 
    | i = c+1 
    | } yield i 
res1: List[Int] = List(2, 3, 4) 
4

स्कैला() में आमतौर पर तब होता है जब आपके पास केवल एक कथन होता है। कुछ इस तरह काम किया होता है:

def encode(number: String): Set[Int] = 
    if (number.isEmpty) Set() 
    else { 
    for (
     split <- 1 to number.length // Only one statement in the comprehension 
    ) split 
    }.toSet 

एक और जोड़े और यह संकलन करने विफल हो जाएगा। एक ही उदाहरण

ठीक

List(1,2,3).map(number => 
    number.toString 
) 

ठीक नहीं है (घुंघराले ब्रेसिज़ का उपयोग करना)

List(1,2,3).map(number => 
    println("Hello world") 
    number.toString 
) 

क्यों कि है के लिए नक्शे के लिए सच है। मुझे नहीं पता कि :)

+0

मुझे एहसास नहीं हुआ था कि बहु-लाइनों की आवश्यकता पहले {} है। अच्छा पकड़ा। – javadba

+1

@javadba कुछ लोग (odersky) हमेशा मल्टीलाइन अभिव्यक्तियों के आसपास ब्रेसिज़ डालते हैं, अन्य (पाउल) एक एकल expr के आसपास माता-पिता पसंद करते हैं जो multiline होता है। 'def f = (if (c) x else y) सूचकांक के लिए ' –

+0

@ som-snytt thx। माता-पिता/ब्रेस 2 मुझे उलझन में डाल रहा है। – javadba