2011-05-26 18 views
7

मुझे आश्चर्य है कि if … elsePredef में विशेष कंपाइलर उपचार के साथ लागू किया जा सकता था, classOf[A] के साथ क्या किया जा रहा है: परिभाषा Predef में है, कार्यान्वयन कंपाइलर द्वारा भरा जाता है।क्या स्कैला का "if ... else" लाइब्रेरी फ़ंक्शन के रूप में कार्यान्वित किया जा सकता है?

दी, बहुत से लोगों को पता है कि एक if हमेशा एक if है आश्वस्त मिलेगा, और एक else हमेशा एक else, कोई फर्क नहीं पड़ता संदर्भ है। हालांकि, if के परिणाम प्रकार पर एक विधि के रूप में else को परिभाषित करना इसे कीवर्ड की सूची से हटा देगा, और लाइब्रेरी डिज़ाइनर को अपने else विधियों को परिभाषित करने की अनुमति देगा। (मुझे पता है कि मैं किसी भी कीवर्ड को बैकटिक्स के साथ पहचानकर्ता के रूप में उपयोग कर सकता हूं, लेकिन `else` जैसे कुछ कोड में भयानक लगते हैं।) ऐसी विधियां this one, discussed on the mailing list जैसी स्थितियों में चर्चा के मामलों में उपयोगी हो सकती हैं, जहां लोगों को otherwise का उपयोग करने के लिए मजबूर होना पड़ता है विधियों को वास्तव में else नाम दिया जाना चाहिए। (इसके अलावा एसओ here और here पर चर्चा की।)

तो:

  • इस तरह के दृष्टिकोण, संभव है यहां तक ​​कि सिद्धांत रूप में, या यह स्काला में कुछ मौलिक सिद्धांत को तोड़ने करता है?
  • डाउनसाइड्स क्या होगा?

उत्तर

10

शायद मैं आपके प्रश्न को समझ नहीं पा रहा हूं, लेकिन आप पहले से ही if ... else ... लाइब्रेरी फ़ंक्शन के रूप में लागू कर सकते हैं। इस पर विचार करें:

class If[A](condition: =>Boolean)(ifBlock: =>A) { 
    def els(elseBlock: =>A):A = condition match { 
    case true => ifBlock 
    case false => elseBlock 
    } 
} 

new If(2==3)(
    println("equal") 
) els (
    println("not equal") 
) 

बेशक यह वास्तव में नहीं करता है क्या if ... else ... करता है, लेकिन कुछ चमकाने के साथ मुझे लगता है कि होगा। मैंने एक बार ऐसी भाषा के लिए एक बहुत ही सरल दुभाषिया लागू किया था जिसमें if ... else ... के साथ बनाए गए पैटर्न मिलान के समान तरीके से लागू किया गया था।

3

सिर्फ if-else, लेकिन किसी भी भाषा सुविधा के रूप में "स्काला वर्चुअलाइज्ड"

https://github.com/TiarkRompf/scala-virtualized

यह स्टैनफोर्ड पीपीएल पर डिलाईट परियोजना का आधार होता है जाना जाता है भाषा की एक शाखा में, अधिरोहित जा सकता है नहीं और स्कैला के यूरोपीय संघ अनुदान द्वारा वित्त पोषित अनुसंधान के केंद्र में भी है। तो आप भविष्य में किसी बिंदु पर कोर भाषा का हिस्सा होने की उम्मीद कर सकते हैं।

+0

महान इस पता करने के लिए! यह वास्तव में अगले तार्किक कदम की तरह दिखता है ... मैं भविष्य के लिए उत्सुक हूं :-) –

3

किसी भी वस्तु उन्मुख भाषा (या क्रम बहुरूपता के साथ किसी भी भाषा) एक पुस्तकालय सुविधा के रूप में सशर्त, विधि प्रेषण के बाद से लागू कर सकते हैं पहले से ही सशर्त के एक अधिक सामान्य रूप वैसे भी है। उदाहरण के लिए, स्मॉलटॉक, विधि प्रेषण को छोड़कर बिल्कुल भी कोई सशर्त नहीं है।

सिंटैक्टिक सुविधा के अलावा, किसी भी प्रकार के कंपाइलर जादू की आवश्यकता नहीं है।

स्काला में, यह हो सकता है देखने के लिए इस तरह एक छोटा सा होगा:

trait MyBooleanLike { 
    def iff[T <: AnyRef](thenn: => T): T 
    def iffElse[T](thenn: => T)(els: => T): T 
    def &&(other: => MyBoolean): MyBoolean 
    def ||(other: => MyBoolean): MyBoolean 
    def nott: MyBoolean 
} 

trait MyTruthiness extends MyBooleanLike { 
    def iff[T](thenn: => T) = thenn 
    def iffElse[T](thenn: => T)(els: => T) = thenn 
    def &&(other: => MyBoolean) = other 
    def ||(other: => MyBoolean) = MyTrue 
    def nott = MyFalse 
} 

trait MyFalsiness extends MyBooleanLike { 
    def iff[T](thenn: => T): T = null.asInstanceOf[T] 
    def iffElse[T](thenn: => T)(els: => T) = els 
    def &&(other: => MyBoolean) = MyFalse 
    def ||(other: => MyBoolean) = other 
    def nott = MyTrue 
} 

abstract class MyBoolean extends MyBooleanLike 

class MyTrueClass extends MyBoolean with MyTruthiness {} 
class MyFalseClass extends MyBoolean with MyFalsiness {} 

object MyTrue extends MyTrueClass {} 
object MyFalse extends MyFalseClass {} 

बस एक छोटे से अंतर्निहित रूपांतरण जोड़ें:

object MyBoolExtension { 
    implicit def boolean2MyBoolean(b: => Boolean) = 
    if (b) { MyTrue } else { MyFalse } 
} 

import MyBoolExtension._ 

और अब हम इसका इस्तेमाल कर सकते हैं:

object Main extends App { 
    (2 < 3) iff { println("2 is less than 3") } 
} 

[नोट: मेरा प्रकार-फू बल्कि कमजोर है। मुझे उचित समय सीमा के भीतर संकलित करने के लिए थोड़ा सा धोखा देना पड़ा। स्कैला के प्रकार की प्रणाली की बेहतर समझ रखने वाला कोई भी इसे ठीक करना चाहता है। इसके अलावा, अब मैं इसे देखता हूं, 8 कक्षाएं, लक्षण और वस्तुएं, उनमें से दो अमूर्त, थोड़ा अधिक इंजीनियर लगती हैं ;-)]

बेशक, पैटर्न मिलान के लिए भी यही सच है। पैटर्न मिलान वाले किसी भी भाषा को अन्य प्रकार की सशर्त की आवश्यकता नहीं होती है, क्योंकि पैटर्न मिलान किसी भी तरह से सामान्य है।

:

+0

अवधारणा के बहुत अच्छे प्रमाण के लिए बहुत बहुत धन्यवाद! मुझे एहसास है कि ऐसा इस तरह किया जा सकता है। मेरा सवाल यह था कि यदि 'लाइब्रेरी फ़ंक्शन' के रूप में, 'if ... else' का वर्तमान रूप लागू किया जा सकता था। मुझे लगता है कि आप और किम स्टीबेल ने दिखाया है कि यह है। –

+0

टिप्पणियों के बिना इस उत्तर पर डाउनवोट क्यों? –

8

संक्षिप्त उत्तर "हाँ" है [BTW यह मूलतः this Ruby code के एक बंदरगाह मैं मनोरंजन के लिए कुछ साल पहले लिखा है।]; कुछ भविष्यवाणियों पर ब्रांचिंग तर्क लाइब्रेरी फ़ंक्शन के रूप में कार्यान्वित किया जा सकता है।

यह इंगित करने लायक है कि, विक्टर क्लैंग और अन्य ने ध्यान दिया है, अगर/और अनिवार्य रूप से एक बूलियन फोल्ड कर रहा है। तह कुछ ऐसा होता है जो हम अक्सर करते हैं - कभी-कभी यह स्पष्ट और स्पष्ट होता है, और कभी-कभी नहीं।

// Either#fold is explicit 
scala> Left[String, Double]("fail") fold(identity, _ + 1 toString) 
res0: java.lang.String = fail 

scala> Right[String, Double](4) fold(identity, _ + 1 toString) 
res1: java.lang.String = 5.0 

एक विकल्प को फोल्ड करना स्पष्ट रूप से नहीं किया जा सकता है, लेकिन हम इसे हर समय करते हैं।

// Option has no fold - wont compile! 
Some(5) fold(1+, 0) 

// .. but the following is equivalent and valid 
scala> Some(5) map(1+) getOrElse(0) 
res3: Int = 6 

एक बुलियन पर ब्रांचिंग तर्क भी एक गुना है, और आप तदनुसार बूलियन को भंग कर सकते हैं। आलसी मूल्यांकन प्राप्त करने के लिए उप-नाम पैरामीटर के उपयोग पर ध्यान दें। इस सुविधा के बिना, ऐसा कार्यान्वयन संभव नहीं होगा।

// pimped Boolean - evaluates t when true, f when false 
class FoldableBoolean(b: Boolean) { 
    def fold[A](t: => A, f: => A) = 
    if(b) t else f 
} 

implicit def b2fb(b: Boolean) = new FoldableBoolean(b) 

अब हम Booleans गुना कर सकते हैं:

scala> true fold("true!", "false") 
res24: java.lang.String = true! 

scala> false fold("true!", "false") 
res25: java.lang.String = false 
+0

विकल्प में 2.10 के रूप में फोल्ड विधि है –

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