स्काला का अपरिवर्तनीय सेट अपने प्रकार में सहसंयोजक क्यों नहीं है?


94

EDIT : मूल उत्तर पर आधारित इस प्रश्न को फिर से लिखा गया

scala.collection.immutable.Setवर्ग अपनी प्रकार पैरामीटर में covariant नहीं है। ऐसा क्यों है?

import scala.collection.immutable._

def foo(s: Set[CharSequence]): Unit = {
    println(s)
}

def bar(): Unit = {
   val s: Set[String] = Set("Hello", "World");
   foo(s); //DOES NOT COMPILE, regardless of whether type is declared 
           //explicitly in the val s declaration
}

यह ध्यान देने योग्य है कि foo(s.toSet[CharSequence])ठीक संकलन करता है। toSetयह सिर्फ लपेटता - विधि हे (1) है asInstanceOf
जॉन सुलिवन

1
यह भी ध्यान दें कि foo(Set("Hello", "World"))2.10 पर भी संकलन किया गया है, क्योंकि स्काला सही प्रकार के सेट का अनुमान लगाने में सक्षम है। हालांकि यह अंतर्निहित रूपांतरणों के साथ काम नहीं करता है ( stackoverflow.com/questions/23274033/… )।
LP_

जवाबों:


55

Setकार्यों के रूप में सेट के पीछे की अवधारणा के कारण अपने प्रकार के पैरामीटर में अपरिवर्तनीय है। निम्नलिखित हस्ताक्षरों को चीजों को थोड़ा स्पष्ट करना चाहिए:

trait Set[A] extends (A=>Boolean) {
  def apply(e: A): Boolean
}

यदि Setसहसंयोजक थे A, तो कार्य के विपरीत होने के कारण applyविधि प्रकार Aके पैरामीटर को लेने में असमर्थ होगी । Setसंभावित रूप से इसके विपरीत हो सकता है A, लेकिन यह भी मुद्दों का कारण बनता है जब आप इस तरह की चीजें करना चाहते हैं:

def elements: Iterable[A]

संक्षेप में, सबसे अच्छा समाधान अपरिवर्तनीय डेटा संरचना के लिए, चीजों को अपरिवर्तित रखना है। आप देखेंगे कि immutable.Mapइसके प्रकार के मापदंडों में से एक भी अपरिवर्तनीय है।


4
मुझे लगता है कि यह तर्क "कार्यों के रूप में सेट के पीछे की अवधारणा" के आसपास टिका है - क्या इस पर विस्तार किया जा सकता है? उदाहरण के लिए, "फंक्शन के रूप में एक सेट" क्या फायदे देता है कि मुझे "संग्रह के रूप में सेट करें" नहीं? क्या यह उस सहसंयोजक प्रकार के उपयोग को खोने के लायक है?
oxbow_lakes

23
प्रकार हस्ताक्षर एक बल्कि कमजोर उदाहरण है। एक सेट का "लागू" एक ही बात है क्योंकि इसमें विधि शामिल है। काश, स्काला की सूची सह-संस्करण है और इसमें एक विधि भी शामिल है। सूची में शामिल हस्ताक्षर अलग-अलग हैं, बेशक, लेकिन विधि सेट की तरह ही काम करती है। इसलिए वास्तव में डिजाइन निर्णय को छोड़कर सेट को सह-संस्करण होने से कुछ भी नहीं रोक रहा है।
डैनियल सी। सोबरल

6
सेट गणितीय दृष्टिकोण से बूलियन कार्य नहीं हैं। सेट कुछ समावेशन फ़ंक्शन द्वारा कम नहीं किए गए Zermelo-Fraenkel axioms से "निर्मित" होते हैं । इसके पीछे का कारण रसेल का विरोधाभास है: यदि कुछ भी सेट का सदस्य हो सकता है, तो सेट के सेट आर पर विचार करें जो स्वयं के सदस्य नहीं हैं। फिर प्रश्न पूछें, क्या R, R का सदस्य है?
oxbow_lakes

12
मैं अभी भी इस बात से सहमत नहीं हूं कि सेट के लिए कोविरेंस का त्याग करना इसके लायक था। निश्चित रूप से, यह अच्छा है कि यह एक विधेय है, लेकिन आप आमतौर पर थोड़ा और अधिक क्रिया कर सकते हैं और "सेट" के बजाय "सेट.कंटेन" का उपयोग कर सकते हैं (और यकीनन "सेट। कॉन्सेप्ट" वैसे भी कई मामलों में बेहतर पढ़ता है)।
मैट आर

4
@ मर्टिन: क्योंकि सूची की विधि में कोई भी है, ए नहीं। प्रकार List(1,2,3).contains _है (Any) => Boolean, जबकि प्रकार Set(1,2,3).contains _है res1: (Int) => Boolean
सेठ टिस्सू

52

पर http://www.scala-lang.org/node/9764 मार्टिन ओडर्स्की लिखते हैं:

"सेट के मुद्दे पर, मेरा मानना ​​है कि गैर-विचरण के ताने भी कार्यान्वयनों से होते हैं। सामान्य सेट को हैशटेबल्स के रूप में लागू किया जाता है, जो कि प्रमुख प्रकार के गैर-वैरिएंट सरणियाँ हैं। मैं मानता हूँ कि यह थोड़ा कष्टप्रद अनियमितता है।"

तो, ऐसा लगता है कि इस के लिए एक राजसी कारण का निर्माण करने के लिए हमारे सभी प्रयास गुमराह थे :-)


1
लेकिन कुछ दृश्यों को सरणियों के साथ भी लागू किया जाता है, और अभी भी Seqसहसंयोजक है ... क्या मुझे कुछ याद आ रहा है?
LP_

4
यह तुच्छ रूप से Array[Any]आंतरिक रूप से भंडारण करके हल किया जा सकता है ।
दायां गुना

@ राइटफोल्ड सही है। एक उचित कारण हो सकता है, लेकिन यह ऐसा नहीं है।
पॉल ड्रेपर

6

EDIT : किसी को भी आश्चर्य हो रहा है कि यह उत्तर थोड़ा-सा विषय क्यों लगता है, इसका कारण यह है कि मैंने (प्रश्नकर्ता) प्रश्न को संशोधित किया है।

स्काला के प्रकार का अनुमान इस बात का पता लगाने के लिए पर्याप्त है कि आप कुछ स्थितियों में CharSequences और स्ट्रिंग्स नहीं चाहते हैं। विशेष रूप से, मेरे लिए 2.7.3 में निम्नलिखित काम करता है:

import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")

कैसे के रूप में अपरिवर्तनीय बनाने के लिए। सीधे सेट करें: नहीं। एक कार्यान्वयन अनुकूलन के रूप में, 5 से कम तत्वों के अपरिवर्तनीय।हैसेट्स वास्तव में अपरिवर्तनीय के उदाहरण नहीं हैं। हाशसेट। वे या तो EmptySet, Set1, Set2, Set3 या Set4 हैं। ये वर्ग अचल को उपवर्गित करते हैं। लेकिन अपरिवर्तनीय नहीं।हशसेट।


तुम सही हो; अपने वास्तविक उदाहरण को सरल बनाने की कोशिश में मैंने एक तुच्छ गलती की :-(
oxbow_lakes
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.