2011-09-29 27 views
18

को देखते हुए:आदेश और आदेश दिया और तुलना विकल्प

case class Person(name: String) 

और ऐसा करने के लिए कोशिश कर रहा है: आदेश लापता बारे में एक शिकायत में

scala> List(Person("Tom"), Person("Bob")).sorted 

का परिणाम है।

<console>:8: error: could not find implicit value for parameter ord: Ordering[Person] 
    List(Person("Tom"), Person("Bob")).sorted 

हालांकि इस:

case class Person(name: String) extends Ordered[Person] { 
    def compare(that: Person) = this.name compare that.name } 

ठीक काम करता है के रूप में उम्मीद:

scala> List(Person("Tom"), Person("Bob")).sorted 
res12: List[Person] = List(Person(Bob), Person(Tom)) 

कोई आदेश या implicits शामिल नहीं है, हालांकि।

प्रश्न # 1: यहां क्या हो रहा है? (मेरे पैसे कुछ निहित पर है ...)

हालांकि, इसके बाद के संस्करण और तथ्य यह है कि यह देखते हुए:

scala> Person("Tom") > Person("Bob") 
res15: Boolean = true 

काम करता है, और वह भी इस:

scala> List(Some(2), None, Some(1)).sorted 

से बाहर काम करता है बॉक्स:

res13: List[Option[Int]] = List(None, Some(1), Some(2)) 

मैं उम्मीद होती है कि इस:

scala> Some(2) > Some(1) 

भी काम करेगा, लेकिन यह नहीं करता है:

<console>:6: error: value > is not a member of Some[Int] 
     Some(2) > Some(1) 

प्रश्न # 2: क्यों नहीं, और कैसे मैं प्राप्त कर सकते हैं यह काम करने के लिए?

उत्तर

9

अपने पहले प्रश्न के संबंध में: Ordered[T] फैली Comparable[T]Ordering साथी उद्देश्य यह है कि एक Comparable[T] में बदला जा सकता है किसी भी मूल्य के लिए एक अंतर्निहित Ordering[T] प्रदान करता है:

implicit def ordered[A <% Comparable[A]]: Ordering[A] 

कोई अंतर्निहित रूपांतरण A : Ordering => Ordered[A] नहीं है - यही कारण है कि Some(1) > Some(2) काम नहीं करेगा है।

यह संदिग्ध है कि इस तरह के रूपांतरण को परिभाषित करना एक अच्छा विचार है क्योंकि आप Ordered उदाहरणों में अपनी ऑब्जेक्ट्स को लपेटकर समाप्त कर सकते हैं और फिर उसमें से Ordering बना सकते हैं (और इसी तरह ...)। इससे भी बदतर: आप दो Ordered उदाहरणों को अलग-अलग Ordering उदाहरणों के साथ बना सकते हैं जो निश्चित रूप से आप नहीं चाहते हैं।

2

सूची के sorted विधि की परिभाषा है:

def sorted [B >: A] (implicit ord: Ordering[B]): List[A] 

तो हाँ, निहित बातें हो रही हैं, लेकिन मानक पुस्तकालय में कई वर्गों आप उन्हें पहली आयात करने के लिए बिना उन लोगों के साथ जुड़े अंतर्निहित वस्तुओं की है।

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

ऑपरेटरों का उपयोग करने की क्षमता हासिल करने के लिए, आपको उस वस्तु आयात करने के लिए, उदाहरण के लिए की जरूरत है:

def cmpSome(l:Option[Int], r:Option[Int])(implicit ord:Ordering[Option[Int]]) = { 
    import ord._ 
    l < r 
} 

scala> cmpSome(Some(0), Some(1)) 
res2: Boolean = true 
+0

यह वास्तव में सवाल का जवाब नहीं देता है कि ऑर्डर किए जाने वाले आदेश [टी] जादुई रूप से ऑर्डरिंग [टी] का एक उदाहरण लाता है। और आखिरी तुलना करने के लिए आपको एक विधि क्यों बनाना है? –

+0

मैंने विधि बनाई ताकि मैं ऑर्डरिंग के उदाहरण तक पहुंच प्राप्त कर सकूं। मैं उस उदाहरण की सामग्री आयात करता हूं, इसलिए मैं इसे 'ओपीएस' में अपना अंतर्निहित रूपांतरण प्राप्त कर सकता हूं, जो कुछ तुलना ऑपरेटर को परिभाषित करता है। उसी विधि का उपयोग करके, मुझे अंत में पता चला कि 'ऑर्डर' के लिए निहित रूपांतरण कहां है। http://www.scala-lang.org/api/current/index.html#scala.math.LowPriorityOrderingImplicits – Dylan

+0

लेकिन यह दो विकल्पों की तुलना करने में सक्षम होने के लिए काफी काम करता है? –

23

आप थोड़ा के लिए भी जादुई के लिए डिफ़ॉल्ट-गुंजाइश बोनस implicits स्थापित है, तो आप की तरह विकल्पों की तुलना कर सकते हैं:

scala> import scala.math.Ordering.Implicits._ 
import scala.math.Ordering.Implicits._ 

scala> def cmpSome[T: Ordering](x: Option[T], y: Option[T]) = x < y 
cmpSome: [T](x: Option[T], y: Option[T])(implicit evidence$1: Ordering[T])Boolean 

आयात आप के साथ वर्ग के लिए एक आदेश से एक अंतर्निहित देता है इंफिक्स ऑपरेशंस, ताकि किसी अन्य आयात के बिना ऑर्डरिंग पर्याप्त हो।

+0

बेहतर चाहता था ... लेकिन अभी भी बहुत काम है, शायद मेरी विनम्र राय में नहीं। :) मैं समझता हूं कि यह इस तरह क्यों है, लेकिन उपयोगकर्ता के दृष्टिकोण से यह तार्किक प्रतीत होता है कि आप किसी भी फज़ के बिना दो विकल्पों की तुलना कर सकते हैं कि आप बिना किसी फज़ के उनकी सूची * सॉर्ट कर सकते हैं। ..किसे आपको दूसरे में तुलना करने की ज़रूरत है, है ना? –

+0

आप उन्हें सॉर्ट कर सकते हैं क्योंकि आप एक विधि को कॉल करते हैं जो एक निहित ऑर्डरिंग लेता है। यहां आप एक विधि लिख रहे हैं जो एक निहित आदेश लेता है। कहीं, ऑर्डरिंग को चित्र में प्रवेश करना होगा, क्योंकि मनमाने ढंग से विकल्प [टी] तुलनात्मक नहीं हैं। – extempore

0

मुझे लगता है कि आप समझते हैं कि सॉर्ट नहीं किया जाता है जब आप ऑर्डरिंग में पास नहीं होते हैं और कोई भी दायरे में उपलब्ध नहीं होता है। जब आप ऑर्डर्ड विशेषता से अपनी कक्षा का विस्तार करते हैं तो क्रमबद्ध फ़ंक्शन क्यों काम करता है। जवाब यह है कि जब आप आदेशित विशेषता से विस्तार करते हैं, तो कोड प्रकार के रूप में चेक के रूप में <,> आदि जैसे फ़ंक्शन शामिल होते हैं इसलिए निहित रूपांतरण करने की कोई आवश्यकता नहीं है और इसलिए अनुपस्थित निषेध आदेश के बारे में कोई शिकायत नहीं है।

अपने दूसरे प्रश्न का सवाल है, Some(2) > Some(1) काम नहीं करेगा क्योंकि कुछ विस्तार नहीं करता विशेषता आदेश दिया, न करता वहाँ दायरे में किसी भी निहित समारोह है कि परोक्ष कुछ कार्य है कि करने के लिए एक कुछ धर्मान्तरित होने लगते हैं >

2

अपने दूसरे प्रश्न का उत्तर देने के लिए, आप यह क्यों नहीं कर सकते: Some(2) > Some(1)

आप Some[Int] के बजाय Option[Int] के साथ आयात और काम कर सकते हैं।

@ import scala.math.Ordering.Implicits._ 
import scala.math.Ordering.Implicits._ 
@ Some(2) > Some(1) // doesn't work 
cmd11.sc:1: value > is not a member of Some[Int] 
val res11 = Some(2) > Some(1) 
        ^
Compilation Failed 
@ (Some(2): Option[Int]) > (Some(1): Option[Int]) // Option[Int] works fine 
res11: Boolean = true 
@ Option(2) > Option(1) 
res12: Boolean = true 
@ (None: Option[Int]) > (Some(1): Option[Int]) 
res13: Boolean = false 

अभ्यास में अपने प्रकार शायद Option[Int] का होगा बजाय Some[Int] तो यह इतना बदसूरत नहीं होगा और आप स्पष्ट upcasting जरूरत नहीं होगी।

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