2010-05-17 6 views
7

यह मेरी परियोजना में प्रकार की सुरक्षा का एक परेशानीपूर्ण उल्लंघन है, इसलिए मैं इसे अक्षम करने का एक तरीका ढूंढ रहा हूं। ऐसा लगता है कि यदि कोई फ़ंक्शन एनीरफ (या java.lang.Object) लेता है, तो आप फ़ंक्शन को पैरामीटर के किसी भी संयोजन के साथ कॉल कर सकते हैं, और स्कैला पैरामीटर को टुपल ऑब्जेक्ट में जोड़ देगा और फ़ंक्शन का आह्वान करेगा।स्कैला एकाधिक फ़ंक्शन कॉल पैरामीटर को टुपल में जोड़ता है - क्या इसे अक्षम किया जा सकता है?

मेरे मामले में फ़ंक्शन टुपल की अपेक्षा नहीं कर रहा है, और रनटाइम पर विफल रहता है। मैं उम्मीद करता हूं कि संकलन समय पर इस स्थिति को पकड़ा जाएगा।

object WhyTuple { 
def main(args: Array[String]): Unit = { 
    fooIt("foo", "bar") 
} 
def fooIt(o: AnyRef) { 
    println(o.toString) 
} 
} 

आउटपुट:

(foo,bar) 
+4

ठीक है अगर कोई फ़ंक्शन किसी तर्क के रूप में 'AnyRef' लेता है, तो यह तर्क है कि तर्क कुछ भी हो, नहीं? मेरा मतलब है कि स्कैला स्वचालित रूप से तर्कों को एक टुपल में पैक नहीं करता है, फिर भी आप स्पष्ट रूप से एक ट्यूपल पास कर पाएंगे, जो निश्चित रूप से पूरी तरह से टाइप-सुरक्षित है क्योंकि आपका फ़ंक्शन कुछ भी लेता है और टुपल्स कुछ भी होता है। यदि आपका फ़ंक्शन केवल कुछ प्रकार के तर्कों को संभाल सकता है तो इसे या तो इन प्रकार के तर्कों को लेने या तर्कसंगत रूप से तर्क प्रकार की जांच करने के लिए घोषित किया जाना चाहिए। – sepp2k

+0

तो यह क्या उम्मीद करता है? आपको इसे विभिन्न विशेषज्ञों में तोड़ना पड़ सकता है। बेशक, अगर आप टुपल के अलावा कुछ भी उम्मीद कर रहे हैं, तो इससे कोई मदद नहीं होगी। – sblundy

+1

पर्याप्त मेला ... लेकिन आम तौर पर अनुबंध (अन्य प्रोग्रामिंग भाषाओं में) यदि कोई फ़ंक्शन 1 पैरामीटर की अपेक्षा करता है और 2 के साथ कॉल किया जाता है, तो संकलन विफल हो जाएगा। –

उत्तर

1

संकलन दौर कोष्ठक के बिना तरीकों व्याख्या करने में सक्षम है। तो यह फू में राउंड ब्रैकेट लेता है इसका मतलब टुपल है।

fooIt(("foo","bar")) 

कहा जा रहा है, तो आप विधि कॉल, और मान प्राप्त बाहर करने के लिए यदि आप Tuple1 (AnyRef) कुछ (AnyRef) जैसे कुछ आवरण या का उपयोग पैदा कर सकता है: आपका कॉल के समान है।

+3

जब तक कि मुझे कुछ याद नहीं आ रहा है, यह प्रश्न के आधार के सारांश के रूप में इतना उत्तर नहीं है। – sepp2k

0

मुझे लगता है कि प्रिडफ में (x, y) की परिभाषा ज़िम्मेदार है। "-Yno-predefs" कंपाइलर ध्वज कुछ उपयोगों का हो सकता है, यह मानते हुए कि आप अन्यथा आवश्यक किसी भी implicits को मैन्युअल रूप से आयात करने के काम को करने के इच्छुक हैं। इसके द्वारा मेरा मतलब है कि आपको जगह पर आयात scala.Predef._ जोड़ना होगा।

+1

-1 सिद्धांत महान हैं, लेकिन पहले उनका परीक्षण क्यों न करें? – retronym

4

संपादित: this answer देखें: लोग मुझ से बेहतर जानकारी के अनुसार, निम्नलिखित जवाब वास्तव में गलत है। इस बिंदु को इंगित करने के लिए धन्यवाद Aaron Novstrup

यह वास्तव में पार्सर का एक क्विर्क है, प्रकार सिस्टम या कंपाइलर नहीं। स्कैला बिना किसी तर्क के शून्य-या एक-तर्क फ़ंक्शंस को बुलाया जा सकता है, लेकिन एक से अधिक तर्क के साथ कार्य नहीं करता है। तो Fred Haslam says के रूप में, आपने जो लिखा है दो तर्कों के साथ एक आमंत्रण नहीं है, यह एक tuple- मूल्यवान तर्क के साथ एक आमंत्रण है। हालांकि, यदि विधि दो तर्क लेती है, तो आमंत्रण दो-तर्क आमंत्रण होगा। ऐसा लगता है कि कोड का अर्थ यह प्रभावित करता है कि यह कैसे पार्स करता है (जो थोड़ा सा चूसना है)।

इस बारे में आप वास्तव में क्या कर सकते हैं, यह मुश्किल है। अगर विधि को वास्तव में दो तर्कों की आवश्यकता होती है, तो यह समस्या दूर हो जाएगी (यानी अगर किसी ने गलती से इसे एक तर्क के साथ या तीन के साथ कॉल करने का प्रयास किया, तो आपको एक संकलन त्रुटि मिल जाएगी जैसा आप उम्मीद करते हैं)। मान लीजिए कि उस अतिरिक्त पैरामीटर को आप उस विधि में जोड़ रहे हैं? :)

+2

एफवाईआई, यदि आप * कॉल * में अधिक पैरामीटर जोड़ते हैं तो आप केवल उच्च स्तरीय टुपल्स के साथ समाप्त होते हैं: fooIt ("foo", "bar", "jam") Tuple3 उत्पन्न करता है। {कॉल पर टिप्पणी, विधि हस्ताक्षर नहीं} –

+0

अच्छा बिंदु, मैं इसे स्पष्ट करने के लिए संपादित करूंगा। –

+1

यह दुर्भाग्यपूर्ण है कि यह उत्तर सबसे अधिक वोट (इस पोस्टिंग के समय) के साथ घायल हो गया है। यह वास्तव में गलत है - देखें [यह] (http://stackoverflow.com/questions/2850902/scala-coalesces-multiple-function-call-parameters-into-a-tuple-can-this-be-dis/2852147# 2852147) और [यह] (http://stackoverflow.com/questions/5997553/why-and-how-is-scala-treating-a-tuple- विशेष रूप से- जब- calling-a-one-arg-function/5998559 # 59 9 8559) –

4

क्या कुछ इस तरह के बारे में:

object Qx2 { 
    @deprecated def callingWithATupleProducesAWarning(a: Product) = 2 
    def callingWithATupleProducesAWarning(a: Any) = 3 
} 

tuples उत्पाद विशेषता, callingWithATupleProducesAWarning को इसलिए किसी भी कॉल है कि एक टपल एक प्रतिवाद चेतावनी का उत्पादन करेगा गुजरता है।

+1

प्यारा, लेकिन वह वैध रूप से विधि के लिए 'उत्पाद' (किसी भी केस क्लास को सोचने) के मूल्य को पास करना चाहता है। – retronym

+0

सच - मैं आलसी हूं। मुझे लगता है कि यदि आपको सामान्य उपयोग में उत्पाद को पास करने की आवश्यकता है तो आपको उन सभी TupleN प्रकारों के लिए एन व्यक्तिगत विधियां जोड़नी होंगी जिन्हें आप सुरक्षित रखना चाहते हैं। –

7

यहां पर कोई प्रभाव या प्रिटफ नहीं है - बस पुराना पुराने फैशन कंपाइलर जादू। आप इसे type checker में पा सकते हैं। मैं इसे अभी spec में नहीं ढूँढ सकता।

यदि आप पर्याप्त प्रेरित हैं, तो आप इसे रोकने के लिए एक -X विकल्प जोड़ सकते हैं।

वैकल्पिक रूप से, आप TupleN के सुपरटेप को स्वीकार करते हुए arity-1 विधियों को लिखने से बच सकते हैं।

+0

http://lampsvn.epfl.ch/trac/scala/ticket/3583 – retronym

0

क्या आप दो-पैरा ओवरराइड भी जोड़ सकते हैं, जो संकलक चीनी को लागू करने वाले संकलक को रोक देगा? प्रकार को अस्पष्ट रूप से अस्पष्ट करने के द्वारा आपको झूठी सकारात्मक प्राप्त करने की संभावना नहीं है। E.g:

object WhyTuple { 

    ... 

    class DummyType 

    def fooIt(a: DummyType, b: DummyType) { 
    throw new UnsupportedOperationException("Dummy function - should not be called") 
    } 
} 
+0

बेशक, यदि आपके पास ऐसी कई विधियां हैं, या यदि आपको 2 से अधिक पैरा के लिए ऐसा करने की आवश्यकता है, तो यह बहुत स्केलेबल नहीं है। – pdbartlett

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

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