2011-09-29 15 views
16

मैं स्कैला के लिए नया हूं। मुझे आश्चर्य है कि विधि कॉल के साथ कुछ प्राथमिकता को परिभाषित करना संभव है या नहीं। उदाहरण के लिए, अगर मैं विधि की श्रृंखला कॉल:स्कैला - विधि प्राथमिकता

someObject.method1(param1).method2(param2.method3(param3)) 

या

someObject method1 param1 method2 (param2 method3 param3) 

तो मैं method3 से प्राथमिकता दी जाती हैं:

someObject method1 param1 method2 param2 method3 param3 

इस निम्नलिखित के बराबर हो सकता है method2 ...

कारण मैं ऐसा करना चाहता हूं कि मैं एक डीएसएल विकसित करना चाहता हूं, इसलिए मैं उपयोग से बचना चाहता हूं जितना संभव हो डॉट्स और कोष्ठक। अगर आप मेरे लिए एक और समाधान पाते हैं, तो मुझे बताने में संकोच न करें।

+2

आप http://www.manning.com/ghosh/ पढ़ सकते हैं (कार्रवाई में DSLs) के रूप में यह मदद मिलेगी एक बड़े सौदे की व्याख्या। वह रूबी, स्कैला (ज्यादातर स्कैला), क्लोजर और ग्रोवी को शामिल करता है। –

उत्तर

3

यह व्यवहार के अध्याय 6.12.3 Infix Operations में परिभाषित किया गया है स्कैला भाषा विशिष्टता

संक्षेप में: कुछ अपवादों के साथ डिफ़ॉल्ट रूप से विधियों को बाएं से दाएं से बुलाया जाता है। इन अपवादों को केवल गणितीय ऑपरेटरों की प्राथमिकता का समर्थन करने के लिए पेश किया गया था। तो अगर आप दो कार्यों * और + नामित किया है:

a.+(b.*(c)) 

यहाँ समारोह का पहला नाम पूर्वता को नियंत्रित करता है:

a + b * c 

यह हमेशा के लिए अनुवाद किया जाएगा। हालांकि सामान्य कार्यों के लिए आप आदेश को नियंत्रित नहीं कर सकते हैं। इसके बारे में सोचें - यह वास्तव में विनाश और बेहद अनजान कोड का कारण बन जाएगा।

यह भी देखें (काफी डुप्लिकेट नहीं?): Operator precedence in Scala

+1

ध्यान दें कि कल्पना गलत है - http://article.gmane.org/gmane.comp.lang.scala/24402 और http://stackoverflow.com/questions/7022207/why-scala-changed-relative-precedence देखें के- रिलेशनल-बनाम-समानता ऑपरेटरों-compar/7022704 # 7022704। – huynhjl

11

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

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

  • कोई भी तरीका जो एक एकल लेता है पैरामीटर को इंफिक्स ऑपरेटर के रूप में उपयोग किया जा सकता है: a.m(b)a m b लिखा जा सकता है।
  • कोई भी विधि जिसे पैरामीटर की आवश्यकता नहीं है उसे पोस्टफिक्स ऑपरेटर के रूप में उपयोग किया जा सकता है: a.ma m लिखा जा सकता है।

  • पोस्टफिक्स ऑपरेटरों इन्फ़िक्स ऑपरेटरों की तुलना में कम पूर्वता है, तो इसका मतलब है foo bar bazfoo.bar(baz) जबकि foo bar baz bam मतलब है (foo.bar(baz)).bam और foo bar baz bam bim मतलब है (foo.bar(baz)).bam(bim)।आप का नाम बदलते हैं

    someObject.method1(param1).method2(param2).method3(param3) 
    

    :

    someObject method1 param1 method2 param2 method3 param3 
    

    के रूप में पार्स किए जाएंगे:

तो बिल्कुल भी जानते हुए भी कि आपके विधि हस्ताक्षर, कर रहे हैं निम्नलिखित कोड (क्योंकि यह सब अक्षरांकीय है) के बिना method3 से |*| या +:+ या जो भी ऑपरेटर समझ में आता है, आप जो भी चाहते हैं उसे प्राप्त कर सकते हैं:

someObject method1 param1 method2 param2 |*| param3 
// same as 
someObject.method1(param1).method2(param2.|*|(param3)) 

उदाहरण के लिए अंतर देखने के लिए:

implicit def pimp(s:String) = new { 
    def |*|(t:String) = t + s 
    def switch(t:String) = t + s 
} 

scala> "someObject" concat "param1" concat "param2" |*| "param3" 
res2: java.lang.String = someObjectparam1param3param2 

scala> "someObject" concat "param1" concat "param2" switch "param3" 
res3: java.lang.String = param3someObjectparam1param2 
+0

आपका उत्तर बहुत उपयोगी है :)। लेकिन मैं वास्तव में चाहता हूं कि मेरा डीएसएल समझने में आसान हो और उपयोग करने में सहज हो, इसलिए मैं गैर-अल्फान्यूमेरिक वर्णों के साथ विधियों का उपयोग नहीं कर सकता। विधि नाम के लिए अक्षरों और गैर-अल्फान्यूमेरिक वर्णों को मिश्रण करने का कोई तरीका है ??? – Peter

+0

@ पीटर, इस तरह से उपयोगी नहीं है। आप एक विधि 'foo_?' या 'foo _ #% ^' नाम दे सकते हैं, लेकिन यह विधि का पहला अक्षर है जो प्राथमिकता निर्धारित करता है और यदि विधि नाम ऑपरेटर चरित्र से शुरू होता है तो इसे पूरी तरह से ऑपरेटर वर्णों से बनाया जाना चाहिए। ध्यान दें कि यदि आप विशेष वर्णों का उपयोग करते हैं तो डीएसएल अभी भी सहज हो सकता है लेकिन आपको सावधान रहना होगा। उदाहरण के लिए मुझे http://www.scala-lang.org/api/current/scala/sys/process/ProcessBuilder.html में अधिकांश ऑपरेटरों को याद रखना आसान लगता है, जबकि मुझे http: // प्रेषण के साथ कठिन समय है .databinder.net/दो + हैंडलर + हैं + बेहतर + से + One.html। – huynhjl

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