स्काला में गोल्फ के लिए टिप्स


24

स्काला में गोल्फिंग के लिए आपके पास क्या सामान्य सुझाव हैं? मैं उन विचारों की तलाश कर रहा हूं जो सामान्य रूप से कोड की समस्याओं को लागू कर सकते हैं जो कम से कम कुछ हद तक स्काला के लिए विशिष्ट हैं (उदाहरण के लिए "टिप्पणियां हटाएं" एक उत्तर नहीं है)। कृपया प्रति उत्तर एक टिप पोस्ट करें।

(यह अजगर की बेशर्म नकल है ...)

जवाबों:


5

डिस्क्लेमर: इस उत्तर के भाग यहां पाए गए अन्य उत्तरों के सामान्यीकरण हैं।

अपने तर्क प्रकारों को निर्दिष्ट किए बिना लैम्ब्डा का उपयोग करें

इसे कुछ इस तरह प्रस्तुत करने की अनुमति है: a=>a.sizeइसके बजाय (a:String)=>a.size

पहचानकर्ता के रूप में एएससीआई-प्रतीकों का उपयोग करें।

इनमें शामिल हैं !%&/?+*~'-^<>|। क्योंकि वे अक्षर नहीं हैं, वे पत्र के बगल में रहने पर पार्स हो जाते हैं।

उदाहरण:

a=>b       //ok
%=>%        //error, parsed as one token
% => %      //ok
val% =3     //ok
&contains+  //ok
if(x)&else* //ok

सेट के बजाय उपयोग करें

if (Seq(1,2,3,'A')contains x)... //wrong
if (Set(1,2,3,'A')(x))...         //right

ऐसा संभव है Set[A] extends (A => Boolean)

जब आपको दो तर्कों की आवश्यकता हो, तो एक करीने वाले फ़ंक्शन का उपयोग करें।

(a,b)=>... //wrong
a=>b=>...  //right

_जब संभव हो तब -syntax का उपयोग करें

इसके लिए नियम कुछ हद तक अस्पष्ट हैं, आपको सबसे छोटा रास्ता खोजने के लिए कभी-कभी थोड़ा सा खेलना होगा।

a=>a.map(b=>b.size)) //wrong
a=>a.map(_.size)     //better
_.map(_.size)        //right

आंशिक अनुप्रयोग का उपयोग करें

a=>a+1 //wrong
_+1    //better, see above
1+     //right; this treats the method + of 1 as a function

के ""+बजाय का उपयोग करेंtoString

a=>a.toString //wrong
a=>a+""       //right

क्रम के रूप में तार का उपयोग करें

"" यदि आप एक्टुला प्रकार की परवाह नहीं करते हैं, तो कभी-कभी एक खाली अनुक्रम बनाने का सबसे छोटा तरीका है

संख्याओं को स्ट्रिंग से और में बदलने के लिए BigInt का उपयोग करें

बेस 10 के अलावा अन्य संख्या को आधार में स्ट्रिंग में बदलने का सबसे छोटा तरीका बिगआईंट की toString(base: Int)विधि है

Integer.toString(n,b) //wrong
BigInt(n)toString b   //right

यदि आप किसी स्ट्रिंग को संख्या में बदलना चाहते हैं, तो उपयोग करें BigInt.apply(s: String, base: Int)

Integer.parseInt(n,b) //wrong
BigInt(n,b)           //right

विदित हो कि यह एक BigInt लौटाता है, जो कई बार एक नंबर की तरह प्रयोग करने योग्य होता है, लेकिन उदाहरण के लिए एक अनुक्रम के रूप में इसका उपयोग नहीं किया जा सकता है।

अनुक्रम बनाने के लिए Seq का उपयोग करें

a::b::Nil   //wrong
List(...)   //also wrong
Vector(...) //even more wrong
Seq(...)    //right
Array(...)  //also wrong, except if you need a mutable sequence

वर्णों के अनुक्रम के लिए स्ट्रिंग्स का उपयोग करें:

Seq('a','z') //wrong
"az"         //right

अनंत दृश्यों के लिए स्ट्रीम का उपयोग करें

कुछ चुनौतियाँ अनंत अनुक्रम के n-वें तत्व के लिए पूछती हैं। इसके लिए स्ट्रीम सही उम्मीदवार है। याद रखें Stream[A] extends (Int => A), कि, एक सूचकांक उस सूचकांक पर तत्व से एक फ़ंक्शन है।

Stream.iterate(start)(x=>calculateNextElement(x))

अपने चिंताजनक समकक्षों के बजाय प्रतीकात्मक ऑपरेटरों का उपयोग करें

:\और के :/बजाय foldRightऔरfoldLeft

a.foldLeft(z)(f) //wrong
(z/:a)(f)        //right
a.foldRight(z)(f) //wrong
(a:\z)(f)         //right

hashCode -> ##

throw new Error() -> ???

का प्रयोग करें &और |के बजाय &&और||

वे बूलियन के लिए समान काम करते हैं, लेकिन हमेशा दोनों ऑपरेंड का मूल्यांकन करेंगे

कार्यों के रूप में एलियास लंबी विधि

def r(x:Double)=math.sqrt(x) //wrong
var r=math.sqrt _            //right; r is of type (Double=>Double)

मानक पुस्तकालय में कार्यों को जानें

यह विशेष रूप से संग्रह के तरीकों पर लागू होता है।

बहुत उपयोगी तरीके हैं:

map
flatMap
filter
:/ and :\ (folds)
scanLeft and scanRight
sliding
grouped (only for iterators)
inits
headOption
drop and take
collect
find
zip
zipWithIndex3
distinct and/or toSet
startsWith

11

किसी चीज़ को दोहराने का सबसे छोटा तरीका है Seq.fill

1 to 10 map(_=>println("hi!")) // Wrong!
for(i<-1 to 10)println("hi!") // Wrong!
Seq.fill(10)(println("hi!")) // Right!

10

संदिग्ध पहचानकर्ता:

आप उपयोग कर सकते हैं ? पहचानकर्ता के रूप में:

val l=List(1,2,3)
val? =List(1,2,3)

यहाँ यह आपको कुछ भी नहीं बचाता है, क्योंकि आप इसे समान संकेत पर नहीं रख सकते हैं:

val ?=List(1,2,3) // illegal

लेकिन बाद में, यह अक्सर एक चरित्र बचाता है, क्योंकि आपको एक सीमांकक की आवश्यकता नहीं है:

print(?size)  // l.size needs a dot
def a(? :Int*)=(?,?tail).zipped.map(_-_)

हालांकि, यह अक्सर उपयोग करने के लिए मुश्किल है:

       print(?size)
3
       print(?size-5)
<console>:12: error: Int does not take parameters
       print(?size-5)
              ^

9

संग्रह

एक यादृच्छिक संग्रह के लिए पहली पसंद अक्सर सूची होती है । कई मामलों में आप इसे Seq से बदल सकते हैं , जो एक वर्ण इंस्टेंटन को बचाता है। :)

के बजाय

val l=List(1,2,3)
val s=Seq(1,2,3)

और, जबकि s.head और s.tail सामान्य कोड में अधिक सुरुचिपूर्ण है, s(0)फिर से एक वर्ण से छोटा है s.head

कुछ मामलों में भी कम - आवश्यक कार्यक्षमता के आधार पर टपल है:

val s=Seq(1,2,3)
val t=(1,2,3)

3 वर्णों को तुरंत सहेजना, और अभिगमन के लिए:

s(0)
t._1

यह प्रत्यक्ष सूचकांक पहुंच के लिए समान है। लेकिन विस्तृत अवधारणाओं के लिए, टुपल्स विफल होते हैं:

scala> s.map(_*2)
res55: Seq[Int] = List(2, 4, 6)

scala> t.map(_*2)
<console>:9: error: value map is not a member of (Int, Int, Int)
       t.map(_*2)
         ^

अद्यतन करें

def foo(s:Seq[Int])
def foo(s:Int*)

पैरामीटर घोषणा में, Int * Seq [Int] पर 4 अक्षर बचाता है। यह समकक्ष नहीं है, लेकिन कभी-कभी, Int * करेगा।


8

आप आमतौर पर mapइसके बजाय उपयोग कर सकते हैं foreach:

List("a","b","c") foreach println

से बदला जा सकता है

List("a","b","c") map println

एकमात्र अंतर रिटर्न प्रकार ( Unitबनाम List[Unit]) है, जिसका उपयोग करते समय आप किसी भी तरह से रुचि नहीं रखते हैं foreach


7

छोटे प्रकार को परिभाषित करें:

यदि आपके पास एक प्रकार की कई घोषणाएं हैं, जैसे

def f(a:String,b:String,c:String) 

यह एक प्रकार का उपनाम परिभाषित करने के लिए कम है, और इसके बजाय इसका उपयोग करें:

type S=String;def f(a:S,b:S,c:S)

मूल लंबाई 3 * 6 = 18 रिप्लेसमेंट-कोड है 8 (टाइप S =?) + 6 + 3 * 1 (= नया रंग) = 17

अगर (n * लंबाई <8 + लंबाई + n), तो यह एक फायदा है।

उन कक्षाओं के लिए जो किसी कारखाने के माध्यम से तात्कालिक हैं, हम उस वस्तु को इंगित करने के लिए एक छोटा चर नाम सेट कर सकते हैं। के बजाय:

val a=Array(Array(1,2),Array(3,4))

हम लिख सकते है

val A=Array;val a=A(A(1,2),A(3,4))

यह #defineउदाहरण के लिए C ++ के साथ भी लागू होता है , लेकिन मैं मानता हूं कि यह अच्छा है defऔर valछोटे हैं।
मैथ्यू पढ़ें

हम्म। defएक विधि को परिभाषित करने के लिए कीवर्ड है, और c ++ के लिए एक सरल अनुवाद val'कॉन्स्ट' है, और यह एक घोषणा है, लेकिन प्रकार अक्सर अनुमानित है। छोटा होना पहले मामले में type=है typedef- जो करीब है - है ना? दूसरा उदाहरण मुझसे नहीं है और यह मेरे लिए नया है। मुझे यह देखना होगा कि इसका उपयोग कहां किया जाए।
उपयोगकर्ता अज्ञात

typedef long long ll;के रूप में ही है #define ll long long, इसलिए बाद के 1. से छोटा है, लेकिन हाँ, typedefकाम करता है। valउदाहरण को फिर से देखकर मैंने निश्चित रूप से इसे गलत समझा। यह स्काला-विशिष्ट भी कम लगता है। x = thingWithAReallyLongComplicatedNameForNoReasonएक बहुत ही सामान्य रणनीति है: P
मैथ्यू पढ़ें

@userunknown जब आप सिंटैक्स के साथ Listया Arrayआदि को इंस्टेंट करते हैं तो आप val x = List(1,2,3)केवल ऑब्जेक्ट applyपर विधि को बुला रहे हैं List। (ऑब्जेक्ट निर्माण के लिए इस तकनीक को "फ़ैक्टरी विधि" के रूप में जाना जाता है, इसके साथ एक कंस्ट्रक्टर का उपयोग करने के विपरीत new।) तो ऊपर, हम सिर्फ एक नया चर बना रहे हैं जो एक ही सिंगलटन ऑब्जेक्ट को चर नाम के रूप में इंगित करता है Array। चूंकि यह एक ही बात है, सहित सभी विधियाँ applyउपलब्ध हैं।
लुइगी प्लिंज

7

.वर्णों की आवश्यकता को हटाने के लिए infix सिंटैक्स का उपयोग करें । जब तक आसन्न आइटम अल्फ़ान्यूमेरिक में या ऑपरेटर वर्णों में दोनों ( यहाँ देखें ), और आरक्षित वर्णों (कोष्ठक, कॉमा आदि) द्वारा अलग नहीं किए जाते हैं, तब तक आपको रिक्त स्थान की आवश्यकता नहीं है ।

उदाहरण के लिए

List(1,2,3,4).filter(_ % 2 == 0) // change to:
List(1,2,3,4)filter(_%2==0)

7

trueऔर falseशाब्दिक रूप में लिखने के लिए अपेक्षाकृत कम होता है 2>1सच के लिए और 1>2झूठे के लिए



6

उनका नाम बदलें, यदि उनका नाम लंबा है, और यदि वे कई बार उपयोग किए जाते हैं - वास्तविक विश्व उदाहरण:

 x.replaceAll(y,z)

 type S=String; def r(x:S,y:S,z:S)=x.replaceAll(y,z)

अलग-अलग स्थानों पर भी 'S = स्ट्रिंग' को बचाने की संभावना के आधार पर, यह केवल किफायती होगा, यदि आप कम से कम 3 बार बदलें।


3

एक बार एक ट्यूपल का उपयोग करते हुए कई चर शुरू करें:

var(a,b,c)=("One","Two","Three") //32 characters

बनाम

var a="One";var b="Two";var c="Three" //37 characters

0

आप फ़ंक्शन परिभाषाओं के लिए उपयोग करने के बजाय भी उपयोग कर सकते हैं =>


1
नमस्कार और पीपीसीजी में आपका स्वागत है। चूंकि अधिकांश समय, उत्तर वर्णों के बजाय बाइट्स में गिने जाते हैं, आपके टिप में केवल एक सीमित गुंजाइश है। मैं इसे संबोधित करूंगा और चरित्र गणना आधारित कोड गोल्फ चुनौतियों में शॉर्टनिंग फ़ंक्शन परिभाषाओं की तरह एक टिप शीर्षक भी जोड़ूंगा
जोनाथन फ्रेच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.