2011-01-15 8 views
13

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

def length2(x:String) = x.length * 2
अब, मैं इसे दोनों तरीकों से लिख सकता हूं:
"aoeu" |> length2 
length2("aoeu")
लेकिन यदि मैं इस फ़ंक्शन को अधिक सामान्य बना देता हूं, तो यह काम करना बंद कर देता है।
def length2(x:SeqLike[_,_]) = x.length * 2 
length2("aoeu") // ok 
"aoeu" |> length2 // doesn't work
क्यों संकलक इसे समझ में नहीं आता है? SeqLike विशेषता में कुछ वर्ग मिश्रण के लिए String से निश्चित रूप से एक अंतर्निहित रूपांतरण है।

+0

ट्रिकी। सबसे पहले मैंने सोचा था कि ऐसा इसलिए है क्योंकि आप एक समय में केवल एक निहित हो सकते हैं, लेकिन अब ऐसा लगता है कि यह कहीं भी एक भिन्नता मुद्दा हो सकता है ... – Debilski

+2

@ डेबिलस्की, मुझे यकीन नहीं है कि '|>' को स्केलज़ में परिभाषित किया गया है, लेकिन जब मैंने अपना खुद का परिभाषित करने की कोशिश की, मुझे लगता है कि "केवल एक निहित नियम" इसे लागू करने से रोका गया है: "एओयू" को '|>' विधि के साथ कक्षा में रूपांतरित करने की आवश्यकता होगी और फिर फिर से 'सेक्लाइक' तक। – huynhjl

+1

त्रुटि संदेश दिखाएं। स्कालज़ में आसानी से उपलब्ध नहीं है, लेकिन त्रुटि संदेश आमतौर पर बताते हैं कि क्या गलत हो रहा है। –

उत्तर

12
scala> "aoeu" |> length2 
<console>:14: error: type mismatch; 
found : (scala.collection.SeqLike[_, _]) => Int 
required: (java.lang.String) => ? 
     "aoeu" |> length2 

त्रुटि संदेश बहुत स्पष्ट है।

हालांकि String से SeqLike[_,_] को एक अंतर्निहित रूपांतरण नहीं है, वहाँ (SeqLike[_, _]) => Int से String => ? करने के लिए कोई रूपांतरण है।

यह निम्न अंतर्निहित रूपांतरण का उपयोग तय किया जा सकता है:

implicit def liftFun[X, T <% X, U](f: (X) => U): (T) => U = { 
    def g(t:T) = f(t) 
    g _ 
} 

संपादित 2: यहाँ एक गैर scalaz ऑपरेटर है।

class Pipe[T](t:T) { 
    def |%>[X, U](f: (X) => U)(implicit ev: T <%< X) = f(t) 
} 
implicit def toPipe[T](t:T) = new Pipe(t:T) 

तो फिर तुम इसे इस तरह उपयोग कर सकते हैं:

def l1(a:String) = a.length 
def l2(a:Seq[_]) = a.length * 2 

"abc" |%> l1 
"abc" |%> l2 

यह |%> की अनुमति देता है एक समारोह है कि जब तक एक T पर लेकिन एक X पर सीधे काम नहीं करता है के रूप में वहाँ एक अंतर्निहित का सबूत है लेने के लिए T से X से रूपांतरण।

2

आवश्यक होने तक अस्तित्वहीन प्रकारों का उपयोग न करें। वे चीजों को तोड़ते हैं, और यहां जरूरी नहीं है।

दूसरी ओर, दूसरे उत्तर में त्रुटि में देखकर चीजों को और स्पष्ट कर दिया गया। जब आप |> का उपयोग करते हैं तो आप के लिए दो निहित रूपांतरण पूछे जा रहे हैं। यह काम करता है अगर आप इसे इस तरह के बजाय घोषित:

def length2[CC <% SeqLike[_, _]](x: CC) = x.length * 2 
+1

यह रिटर्न: 'प्रकार के सबूत पैरामीटर (सीसी) => scala.collection.SeqLike [_, _] 'के लिए अंतर्निहित मूल्य नहीं मिला – huynhjl