2012-01-03 17 views
13

Option के लिए Traversable नहीं होने के लिए कोई तर्कसंगत है?विकल्प क्यों नहीं है?

स्कैला 2.9, Seq(Set(1,3,2),Seq(4),Option(5)).flatten संकलित नहीं करता है और इसे Traversable विशेषता उत्तेजना को लागू करने के लिए इसे संकलित नहीं करता है। यदि यह मामला नहीं है, तो ऐसा कुछ होना चाहिए जो मुझे नहीं लगता है कि इसे अनुमति न दें। यह क्या है?

पुनश्च:

scala> Seq(Set(1,3,2),Seq(4),Map("one"->1, 2->"two")).flatten 
res1: Seq[Any] = List(1, 3, 2, 4, (one,1), (2,two)) 

पीएस 2: को समझने के लिए प्रयास करते समय, मैं भयानक चीजें हैं जो संकलन, की तरह हासिल की मैं जानता हूँ कि मैं लिख सकते हैं: Seq(Set(1,3,2),Seq(4),Option(5).toSeq).flatten या अन्य बदसूरत बात।

PS3:, commitanother commit

+2

भाषा के लिए (या इस मामले में पुस्तकालय) इस तरह के डिजाइन प्रश्न, आमतौर पर भाषा (या पुस्तकालय) डिजाइनरों से सीधे पूछना सर्वोत्तम होता है। वे मेलिंग सूची पर बहुत ही संवेदनशील हैं लेकिन कभी-कभी कभी-कभी स्टैक ओवरफ्लो पर जाते हैं। –

+4

@ JörgWMittag SO पर संकलित उत्तर होना अच्छा लगेगा, हालांकि .. –

उत्तर

5

flatMapTraversable के बजाय Option लौटने में चुनौतियां हो सकती हैं। हालांकि यह पूरे 2.8 CanBuildFrom मशीनरी की भविष्यवाणी करता है।

प्रश्न मेलिंग सूची पर एक बार पहले asked था लेकिन प्रतिक्रिया प्राप्त नहीं हुई।

sealed trait OptionX[+A] extends Traversable[A] { 
    def foreach[U](f: (A) => U): Unit = if (!isEmpty) f(get) 
    def get: A 
    def isDefined: Boolean 
    def getOrElse[B >: A](default: => B): B 
} 

case class SomeX[+A](a: A) extends OptionX[A] { 
    override def isEmpty = false 
    def get = a 
    def isDefined = true 
    def getOrElse[B >: A](default: => B) = a 
} 

case object NoneX extends OptionX[Nothing] { 
    override def isEmpty = true 
    def get = sys.error("none") 
    def isDefined = false 
    def getOrElse[B](default: => B) = default 
} 

object O extends App { 
    val s: OptionX[Int] = SomeX(1) 
    val n: OptionX[Int] = NoneX 
    s.foreach(i => println("some " + i)) 
    n.foreach(i => println("should not print " + i)) 
    println(s.map(_ + "!")) 
} 

अंतिम पंक्ति List("1!")Option के बजाय रिटर्न:

यहाँ एक उदाहरण है। हो सकता है कि कोई 10 के साथ आ सकता है जो SomeX("1!") उत्पन्न करेगा। मेरे प्रयास सफल नहीं हुआ:

object OptionX { 
    implicit def canBuildFrom[Elem] = new CanBuildFrom[Traversable[_], Elem, OptionX[Elem]] { 
    def builder() = new Builder[Elem, OptionX[Elem]] { 
     var current: OptionX[Elem] = NoneX 
     def +=(elem: Elem): this.type = { 
     if (current.isDefined) sys.error("already defined") 
     else current = SomeX(elem) 
     this 
     } 
     def clear() { current = NoneX } 
     def result(): OptionX[Elem] = current 
    } 
    def apply() = builder() 
    def apply(from: Traversable[_]) = builder() 
    } 
} 

मैं स्पष्ट रूप से निहित पारित करने के लिए की जरूरत है:

scala> import o._ 
import o._ 

scala> val s: OptionX[Int] = SomeX(1) 
s: o.OptionX[Int] = SomeX(1) 

scala> s.map(_+1)(OptionX.canBuildFrom[Int]) 
res1: o.OptionX[Int] = SomeX(2) 

scala> s.map(_+1) 
res2: Traversable[Int] = List(2) 

संपादित करें:

तो मैं समस्या के समाधान और SomeX(1).map(1+) वापसी एक है करने में सक्षम था OptionXOptionXTraversableLike[A, OptionX[A]] बढ़ाकर newBuilder ओवरराइड कर रहा है।

लेकिन फिर मुझे SomeX(1) ++ SomeX(2) या for (i <- SomeX(1); j <- List(1,2)) yield (i+j) पर रनटाइम त्रुटियां मिलती हैं। तो मुझे नहीं लगता कि यह संभव है कि विकल्प Traversable बढ़ाएं और सबसे विशिष्ट प्रकार को वापस करने के मामले में कुछ सायन करें।

व्यवहार्यता से परे, शैली के अनुसार कोडिंग, मुझे यकीन नहीं है कि OptionTraversable की तरह सभी परिस्थितियों में व्यवहार करना अच्छी बात है। Option उन मानों का प्रतिनिधित्व करते हैं जिन्हें हमेशा परिभाषित नहीं किया जाता है, जबकि Traversable संग्रहों के तरीकों को परिभाषित करता है जिनमें drop(n), splitAt(n), take(n), ++ जैसे कई तत्व हो सकते हैं। यद्यपि यह सुविधा प्रदान करेगा यदि Option भी Traversable था, मुझे लगता है कि यह इरादा कम स्पष्ट कर सकता है।

toSeq का उपयोग करना जहां आवश्यक है दर्दनाक तरीके की तरह लगता है कि मैं अपना विकल्प Traversable जैसा व्यवहार करना चाहता हूं। शायद मैं

  • List(Option(1), Option(2), None).flatten
  • for (i <- List(0,1); j <- Some(1)) yield (i+j)
  • Some(1) ++ Some(2)
+0

अच्छा उत्तर, धन्यवाद – shellholic

1

कारण यह है कि implicits के साथ कुछ मामलों में लागू प्रकार कम सटीक मिलेगा है: वहाँ पिछले महीने में काम लागू बिना Traversable तरह Option नज़र अधिक बनाने के लिए होने के लिए तेजी। आपके पास अभी भी Option मान होगा, लेकिन स्थिर वापसी प्रकार Iterable, ई जैसा होगा। जी। "सबसे सटीक" नहीं।

1

: तो उदाहरण के लिए यह पहले से ही काम करता है (वे सब लौट List(1,2)) - और कुछ आवर्ती उपयोग के मामलों के लिए, वहाँ option2Iterable अंतर्निहित रूपांतरण है मैं घना हो रहा हूं, लेकिन मुझे समझ में नहीं आता कि किसी को इसकी आवश्यकता क्यों होगी। इसके अलावा, NoneTraversable होने के साथ-साथ अर्थात् संदिग्ध लगता है।

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

+1

'शून्य '' ट्रैवर्सबल' – shellholic

+0

टच है। हालांकि 'नील' और 'कोई नहीं' का मतलब काफी अलग है। 'नील 'सूची [कुछ भी नहीं]' बढ़ाता है और 'सूची()' का मूल्य है। यदि 'नील 'ट्रैवर्सबल' नहीं था तो इससे कई समस्याएं पैदा होंगी :) –

+0

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

4

यह Traversable नहीं है क्योंकि आप इसके लिए scala.collection.mutable.Builder लागू नहीं कर सकते हैं।

ठीक है, यह एक ट्रैवर्सबल भी हो सकता है, लेकिन इसके परिणामस्वरूप Option वापस आने वाली कई विधियां परिणामस्वरूप Traversable लौट रही हैं। यदि आप देखना चाहते हैं कि ये कौन सी विधियां हैं, तो बस उन विधियों को देखें जो CanBuildFrom पैरामीटर लेते हैं।

के प्रदर्शन करने के लिए अपने नमूना कोड लेते हैं क्यों:

Seq(Set(1,3,2),Seq(4),Option(5)).flatten 

कि के बराबर होना चाहिए:

Option(Set(1,3,2),Seq(4),Option(5)).flatten 

क्या है:

Seq(1, 2, 3, 4, 5) 

अब, चलो इस विकल्प पर विचार करते हैं उस का मूल्य?

+2

'विकल्प # लागू' एक पैरामीटर लेता है, और उस मामले में उत्तर है: 'विकल्प (सेट (1,3,2))। Flatten => सेट (1,3,2)' – shellholic

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