2010-09-15 9 views
17

मुझे लगता है कि स्कैला सादगी से बहुत दूर है, इसकी वाक्यविन्यास की तरह। उदाहरण के लिए मार्टिन ओडर्स्की विधि लिखा अपनी पुस्तक में: तरीकों बढ़तास्कैला कोडिंग शैलियों और सम्मेलन?

def calculate(s: String): Int = 
    if (cache.contains(s)) 
    cache(s) 
    else { 
    val acc = new ChecksumAccumulator 
    for (c <- s) 
     acc.add(c.toByte) 
    val cs = acc.checksum() 
    cache += (s -> cs) 
    cs 
    } 

हैं, तो यह बहुत ही दर्दनाक हो जाता है कोड को पढ़ने के लिए, मैं, घुंघराले ब्रेसिज़ से मेल नहीं IDE में विधि गुना नहीं कर सकते हैं कर सकते हैं। क्या वहां कोई स्कैला कोडिंग सम्मेलन है? मुझे लगता है यह एक सरल विधि व्यक्त करने के लिए भी लचीला है:

def add(b: Byte): Unit = { 
    sum += b 
} 

def add(b: Byte): Unit = sum += b 

def add(b: Byte) { sum += b } 
+0

क्या इन कोडिंग सम्मेलनों करने का प्रयास करेंगे में सम्मेलनों का एक बहुत कर रहे हैं? – wheaties

+7

क्योंकि स्कैला में कोड की एक साधारण रेखा व्यक्त करने के बहुत सारे तरीके हैं, कोडिंग सम्मेलन टीमों या समुदायों के भीतर कोड औपचारिक बनाने में मदद करेंगे। – Sawyer

+0

आपके दूसरे कोड उदाहरण में एक सम्मेलन आपके पहले उदाहरण को पठनीयता में कैसे मदद करेगा? – Debilski

उत्तर

35

"विधि यह बहुत ही दर्दनाक हो जाता है कोड को पढ़ने के लिए बढ़ता है"। मुझे लगता है कि जवाब का हिस्सा यह है कि विधियां नहीं बढ़नी चाहिए। कार्यात्मक प्रोग्रामिंग शैली में कई छोटी विधियां हैं। गणना विधि पहले से ही बड़ी तरफ है।

स्कैला प्रोग्रामिंग के लिए स्टाइल गाइड के बारे में अधिक सामान्य प्रश्नों के उत्तर देने के लिए: यहां एक representative example है।

+0

यह विशेष रूप से आसान है क्योंकि आप तरीकों के तरीकों को परिभाषित कर सकते हैं! अपना कोड तोड़ने का एक शानदार तरीका। और जावा में रिकर्सिव कार्यों के लिए निजी साथी तरीकों से काफी अच्छा है। – schmmd

4

विशिष्ट उदाहरण है कि आप क्योंकि यह परिणाम memoize करने के लिए एक कैश उपयोग कर रहा है बोली जटिल लग सकता है। यदि आप ज्ञापन को हटाते हैं, तो विधि कम हो जाती है:

def calculate(s: String): Int = { 
    val acc = new ChecksumAccumulator 
    for (c <- s) 
     acc.add(c.toByte) 
    acc.checksum() 
} 

जो मुझे लगता है, बिल्कुल जटिल नहीं है।

+0

आपके टैब गड़बड़ हो गए हैं। – Det

24

यहां Scala Style Guide का एक लिंक है।


घुंघराले ब्रेसिज़ अनुभाग का कहना है:

घुंघराले-ब्रेसिज़:

घुंघराले-ब्रेसिज़ मामलों में छोड़ दिया जाना चाहिए जहां नियंत्रण संरचना एक pure- कार्यात्मक आपरेशन का प्रतिनिधित्व करता है और नियंत्रण संरचना की सभी शाखाएं ( से संबंधित/यदि अन्य) एकल-पंक्ति अभिव्यक्तियां हैं। याद रखें निम्न दिशानिर्देशों:

  • हैं - न आना धनुकोष्ठक यदि आप एक और को खंड की है। अन्यथा, घुंघराले ब्रेसिज़ के साथ सामग्री को घेरे, भले ही सामग्री केवल एक पंक्ति हो।

  • जबकि - ब्रेसिज़ को कभी न छोड़ें (जबकि शुद्ध-कार्यात्मक तरीके से उपयोग नहीं किया जा सकता है)।

  • - यदि आपके पास उपज क्लॉज है तो ओमिट ब्रेसिज़ के लिए। अन्यथा, घुमावदार ब्रेसिज़ के साथ सामग्री को घेरे, भले ही सामग्री केवल एक पंक्ति है।

  • केस - एक पंक्ति पर केस अभिव्यक्ति टीएस अगर ब्रेसिज़ को छोड़ दें। अन्यथा, स्पष्टता के लिए घुंघराले ब्रेसिज़ का उपयोग करें (भले ही वे पार्सर द्वारा आवश्यक नहीं हैं)।

    val news = if (foo) 
        goodNews() 
    else 
        badNews() 
    
    if (foo) { 
        println("foo was true") 
    } 
    
    news match { 
        case "good" => println("Good news!") 
        case "bad" => println("Bad news!") 
    } 
    

मैं लोगों को इस शैली गाइड :(


कृपया ध्यान दें कि मैं सहमत नहीं हूँ "न आना धनुकोष्ठक अगर if एक else खंड है" के साथ भाग पीछा कामना करते हैं।मैं बहुत इस तरह कोड देखना पसंद करेंगे:

def calculate(s: String): Int = { 
    if (cache.contains(s)) { 
    cache(s) 
    } else { 
    val acc = new ChecksumAccumulator 
    for (c <- s) { 
     acc.add(c.toByte) 
    } 
    val cs = acc.checksum() 
    cache += (s -> cs) 
    cs 
    } 
} 
+1

ब्रैकेट कोड को प्रारूपित करने में मदद करता है, मुझे आपकी शैलियों को भी पसंद है, शायद मैं जावा से आया हूं। – Sawyer

+0

मुझे नहीं पता कि एक सम्मेलन कभी भी अनिवार्य विराम चिह्न की मांग क्यों करेगा। –

+0

@Randall: जावा दुनिया में यह करता है, और एक अच्छे कारण के लिए: यह कोड को रिफैक्टर करने में आसान बनाता है, और पढ़ता है (मेरी राय में)। – missingfaktor

1

यहां उस व्यक्ति का शब्द है जिसने स्कैला, स्वयं और अभी भी इस भाषा का मुख्य कार्यान्वयन लिखा है।

स्रोत: स्काला में कार्यात्मक प्रोग्रामिंग सिद्धांतों मार्टिन ओडर्स्की द्वारा

या अगले भेंट आप भी अब अपने पाठ्यक्रम लेने के लिए आमंत्रित कर रहे हैं link [1]

========== =================

स्काला स्टाइल गाइड मदद

इस पृष्ठ पर आप सामान्य समस्याओं का जिसका हमने पता लगाया है, जबकि कुछ प्रस्तुतियाँ को देखने का एक सूची प्राप्त कर सकते हैं।

कुछ स्टाइल मुद्दों को स्वचालित स्टाइल चेकर द्वारा पता लगाया जा सकता है जिसे हम ग्रेडिंग प्रक्रिया के लिए भी उपयोग करते हैं। स्टाइल चेकर, जो स्केलस्टाइल पर आधारित है, स्टाइल चेक कार्य चलाकर एसबीटी में स्थानीय रूप से निष्पादित किया जा सकता है।

सामान्य समस्याएं

1 से बचें निर्मोक और प्रकार टेस्ट

कभी isInstanceOf या asInstanceOf का उपयोग करें - वहाँ हमेशा एक बेहतर समाधान है, दोनों कार्य के लिए, और किसी भी वास्तविक दुनिया स्काला परियोजना के लिए। यदि आप खुद को कास्ट का उपयोग करना चाहते हैं, तो एक कदम वापस लें और आप जो हासिल करने की कोशिश कर रहे हैं उसके बारे में सोचें। असाइनमेंट निर्देशों को दोबारा पढ़ें और संबंधित व्याख्यान वीडियो पर एक और नज़र डालें।

2 इंडेंटेशन

सुनिश्चित करें कि आपके कोड को ठीक दांतेदार है, यह एक बहुत अधिक पठनीय बन जाता है।

यह हमारे अभ्यास के लिए मामूली और बहुत प्रासंगिक नहीं लग सकता है, लेकिन भविष्य में खुद को एक टीम का हिस्सा बनने की कल्पना करें, अन्य कोडर्स के साथ एक ही फाइल पर काम करना: यह बहुत महत्वपूर्ण है कि हर कोई स्टाइल नियमों को रखने के लिए शैली के नियमों का सम्मान करता है कोड स्वस्थ।

यदि आपका संपादक इंडेंटेशन नहीं करता है जिस तरह से आप इसे चाहते हैं, तो आपको यह पता लगाना चाहिए कि इसकी सेटिंग्स कैसे बदलें। स्कैला में, मानक 2 रिक्त स्थान (कोई टैब) का उपयोग करके इंडेंट करना है।

3 लाइन की लंबाई और व्हाइटस्पेस

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

उदाहरण (लंबी लाइन, लापता रिक्त स्थान):

if(p(this.head))this.tail.filter0(p, accu.incl(this.head))else this.tail.filter0(p, accu) 

बेहतर:

if (p(this.head)) 
    this.tail.filter0(p, accu.incl(this.head)) 
else 
    this.tail.filter0(p, accu) 

भी अच्छी बात है (देखें # 4 और नीचे # 6):

वैल newAccu =

if (p(this.head)) accu.incl(this.head) 
    else accu 
this.tail.filter0(p, newAccu) 

4 स्थानीय का उपयोग करें जटिल अभिव्यक्तियों को सरल बनाने के लिए मूल्य

कार्यात्मक शैली में कोड लिखते समय, अक्सर कार्य कॉल के संयोजन के रूप में विधियों को लागू किया जाता है। यदि ऐसी संयुक्त अभिव्यक्ति बहुत बड़ी हो जाती है, तो कोड समझने में मुश्किल हो सकती है।

ऐसे मामलों में उन्हें फ़ंक्शन में पास करने से पहले स्थानीय मान में कुछ तर्कों को स्टोर करना बेहतर होता है (ऊपर # 3 देखें)। सुनिश्चित करें कि स्थानीय मूल्य का अर्थपूर्ण नाम है (नीचे # 5 देखें)!

5 तरीके के लिए सार्थक नाम चुनें और इतना है कि स्रोत कोड समझने में आसान है मान

विधियां, फ़ील्ड और मूल्यों के नाम ध्यान से चुना जाना चाहिए। विधि विधि को यह स्पष्ट करना चाहिए कि विधि क्या करती है।

val temp = sortFuntion0(list.head, tweet) // what does sortFunction0 do? 
def temp(first: TweetSet, second : TweetSet): TweetSet = ... 
def un(th: TweetSet,acc: TweetSet): TweetSet = ... 
val c = if (p(elem)) accu.incl(elem) else accu 
def loop(accu: Trending, current: TweetSet): Trending = ... 
def help(ch: Char, L2: List[Char], compteur: Int): (Char, Int) = ... 
def help2(L: List[(Char, Int)], L2: List[Char]): List[(Char, Int)] = ... 

6 आम Subexpressions

आप गणना गहन तरीकों में से अनावश्यक आमंत्रण से बचना चाहिए: नहीं, अस्थायी एक अच्छा नाम :-)

कुछ improvable उदाहरण नहीं है। उदाहरण के लिए

this.remove(this.findMin).ascending(t + this.findMin) 

इस पर आमंत्रित करता है। अंतिम विधि दो बार।

val min = this.findMin 
this.remove(min).ascending(t + min) 

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

7 कॉपी-पेस्ट कोड न करें!

कॉपी-पेस्टिंग कोड हमेशा खराब शैली के लिए एक चेतावनी संकेत है! कई नुकसान हैं:

कोड लंबे समय तक है, यह यह को समझने के लिए दो भागों के समान नहीं है, लेकिन बहुत समान हैं, तो अधिक समय लगता है, यह मतभेद को पहचानना बहुत मुश्किल है (नीचे उदाहरण देखें) दो को बनाए रखने प्रतियां और सुनिश्चित करें कि वे सिंक्रनाइज़ रहते हैं बहुत त्रुटि-प्रवण कोड में परिवर्तन करने के लिए आवश्यक काम की मात्रा गुणा आपको सामान्य भागों को कोड को कॉपी करने के बजाय अलग-अलग तरीकों से कारक बनाना चाहिए।उदाहरण (एक और उदाहरण के लिए ऊपर भी # 3 देखें):

val googleTweets: TweetSet = TweetReader.allTweets.filter(tweet => 
    google.exists(word => tweet.text.contains(word))) 
val appleTweets: TweetSet = TweetReader.allTweets.filter(tweet => 
    apple.exists(word => tweet.text.contains(word))) 
This code is better written as follows: 

def tweetsMentioning(dictionary: List[String]): TweetSet = 
    TweetReader.allTweets.filter(tweet => 
    dictionary.exists(word => tweet.text.contains(word))) 

val googleTweets = tweetsMentioning(google) 
val appleTweets = tweetsMentioning(apple) 

8 स्काला अर्धविराम

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

def filter(p: Tweet => Boolean): TweetSet = filter0(p, new Empty); 

9 "प्रिंट" बयान

आप अपने कोड को साफ और प्रस्तुत करने से पहले सभी प्रिंट या println बयान को निकाल देना चाहिए साथ कोड प्रस्तुत न करें। एक बार कंपनी के लिए काम करने और उत्पादन में उपयोग किए जाने वाले कोड बनाने के बाद भी लागू होगा: अंतिम कोड डिबगिंग स्टेटमेंट से मुक्त होना चाहिए।

10 वापसी

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

def factorial(n: Int): Int = { 
    if (n <= 0) return 1 
    else return (n * factorial(n-1)) 
} 

वापसी विवरणों को आसानी से हटाया जा सकता है।

11 से बचें परिवर्तनशील स्थानीय चर

चूंकि यह कार्यात्मक प्रोग्रामिंग पर एक कोर्स है, हम आपको एक पूरी तरह कार्यात्मक शैली में कोड लिखने, एक ओर प्रभावशाली संचालन का उपयोग किए बिना आदत हो करना चाहते हैं। आप अकसर कोड को फिर से लिख सकते हैं जो संवादात्मक लेने वाले सहायक कार्यों के साथ कोड में परिवर्तनीय स्थानीय चर का उपयोग करता है। बजाय:

def fib(n: Int): Int = { 
    var a = 0 
    var b = 1 
    var i = 0 
    while (i < n) { 
    val prev_a = a 
    a = b 
    b = prev_a + b 
    i = i + 1 
    } 
    a 
} 

पसंद करते हैं:

def fib(n: Int): Int = { 
    def fibIter(i: Int, a: Int, b: Int): Int = 
    if (i == n) a else fibIter(i+1, b, a+b) 
    fibIter(0, 0, 1) 
} 

12 को हटा दें

if (cond) true else false 

के बजाय अनावश्यक भाव

"अगर"

आप बस लिख सकते हैं

cond 

(इसी प्रकार negaitve मामले के लिए)।

अन्य स्टाइल मुद्दे? कृपया स्टाइल या स्टाइल चेकटैग का उपयोग करके फ़ोरम पर पोस्ट करें और हम सुझावों के साथ इस स्टाइल गाइड को बढ़ाएंगे।

+2

प्वाइंट # 5 मजाकिया है, यह देखते हुए कि स्कालाडोक सिर्फ 'के', 'जी',' पी', और' z' नामक तर्क नामों से भरा है। – jbx

+0

मैंने यह नहीं देखा जब मैंने लिखा कि भाषा के निर्माता ने यहां पोस्ट किया है। आप वाक्य रचनात्मक सम्मेलनों के बारे में स्कैला के बारे में अपनी पोस्ट पढ़ना चाहेंगे। http://stackoverflow.com/a/3718851/1984636 – sivi

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