सबसे प्रभावी तरीका कच्चे प्रकार के रूप में आदिम संख्या (Int Double ...) को स्टोर करना सबसे प्रभावी तरीका है।
हस्ताक्षर को टाइप पैरामीटर में संग्रहीत किया जाना चाहिए, जिसे रनटाइम पर मिटा दिया जाएगा। स्कैला ऐसा करता है जब आप सरल केस कक्षाओं को AnyVal का विस्तार करते हैं।
फोल्टिंग कोड इंट्स, लॉन्ग्स, डबल्स और बिगिंट के लिए यह करता है। मैंने हस्ताक्षर किए जाने के लिए कुछ वर्गीकरण जोड़े और बिना हस्ताक्षर किए गए सकारात्मक का नाम बदल दिया।
चूंकि वर्गीकरण सभी प्रकार के सिस्टम में किया जाता है, इसलिए हमें कई अधिभारित + - और * फ़ंक्शंस प्रदान करने की आवश्यकता नहीं होती है। यह सभी संख्या प्रकारों के लिए इसे लागू करने का प्रयास करते समय अंतरिक्ष को बचाएगा।
विभिन्न प्रकारों के बीच ब्रिजिंग करते समय अभी भी कुछ किया जाना बाकी है। मैं बाद में इसे देख लूंगा।
वर्गीकरण लक्षण:
sealed trait SignTag{
type SubTag <:SignTag;
type AddTag <:SignTag;
type MultTag<:SignTag;
}
sealed trait Signed extends SignTag{
type SubTag=Signed;
type AddTag=Signed;
type MultTag=Signed;
}
sealed trait Positive extends SignTag{
type SubTag=Signed;
type AddTag=Negative;
type MultTag=Negative;
}
sealed trait Negative extends SignTag{
type SubTag=Signed;
type AddTag=Negative;
type MultTag=Positive;
}
sealed trait Zero extends SignTag{
type SubTag=Zero;
type AddTag=Zero;
type MultTag=Zero;
}
इंट आवरण:
object SInt {
@inline
implicit def toSigned[T <: SignTag](int:SInt[T]):SInt[Signed]=int.asInstanceOf[SInt[Signed]];
@inline implicit def toLong[T <: SignTag](int:SInt[T]):SLong[T]=SLong(int.underlying);
@inline implicit def toDouble[T <: SignTag](int:SInt[T]):SDouble[T]=SDouble(int.underlying);
@inline implicit def toBig[T <: SignTag](int:SInt[T]):SBigInt[T]=SBigInt(int.underlying);
}
case class SInt[T <: SignTag](val underlying:Int) extends AnyVal{
def -(second: SInt[_ <: T#InTag]):SInt[T#SubTag]=new SInt[T#SubTag](underlying - second.underlying);
def +(second: SInt[_ <: T#InTag]):SInt[T#AddTag]=new SInt[T#AddTag](underlying + second.underlying);
def *(second: SInt[_ <: T#InTag]):SInt[T#MultTag]=new SInt[T#MultTag](underlying * second.underlying);
def assertSameType(other:SInt[T])={};
}
लांग आवरण:
object SLong {
@inline
implicit def toSigned[T <: SignTag](int:SLong[T]):SLong[Signed]=int.asInstanceOf[SLong[Signed]];
@inline implicit def toDouble[T <: SignTag](int:SLong[T]):SDouble[T]=SDouble(int.underlying);
@inline implicit def toBig[T <: SignTag](int:SLong[T]):SBigInt[T]=SBigInt(int.underlying);
}
case class SLong[T <: SignTag](val underlying:Long) extends AnyVal{
def -(second: SLong[_ <: T#InTag]):SLong[T#SubTag]=new SLong[T#SubTag](underlying - second.underlying);
def +(second: SLong[_ <: T#InTag]):SLong[T#AddTag]=new SLong[T#AddTag](underlying + second.underlying);
def *(second: SLong[_ <: T#InTag]):SLong[T#MultTag]=new SLong[T#MultTag](underlying * second.underlying);
def assertSameType(other:SLong[T])={};
}
डबल आवरण:
object SDouble {
@inline
implicit def toSigned[T <: SignTag](int:SDouble[T]):SDouble[Signed]=int.asInstanceOf[SDouble[Signed]];
}
case class SDouble[T <: SignTag](val underlying:Double) extends AnyVal{
def -(second: SDouble[_ <: T#InTag]):SDouble[T#SubTag]=new SDouble[T#SubTag](underlying - second.underlying);
def +(second: SDouble[_ <: T#InTag]):SDouble[T#AddTag]=new SDouble[T#AddTag](underlying + second.underlying);
def *(second: SDouble[_ <: T#InTag]):SDouble[T#MultTag]=new SDouble[T#MultTag](underlying * second.underlying);
def assertSameType(other:SDouble[T])={};
}
BigInt आवरण:
object SBigInt {
@inline
implicit def toSigned[T <: SignTag](int:SLong[T]):SLong[Signed]=int.asInstanceOf[SLong[Signed]];
@inline
implicit def toDouble[T <: SignTag](int:SBigInt[T]):SDouble[T]=SDouble(int.underlying.toDouble);
}
case class SBigInt[T <: SignTag](val underlying:BigInt) extends AnyVal{
def -(second: SBigInt[_ <: T#InTag]):SBigInt[T#SubTag]=new SBigInt[T#SubTag](underlying - second.underlying);
def +(second: SBigInt[_ <: T#InTag]):SBigInt[T#AddTag]=new SBigInt[T#AddTag](underlying + second.underlying);
def *(second: SBigInt[_ <: T#InTag]):SBigInt[T#MultTag]=new SBigInt[T#MultTag](underlying * second.underlying);
def assertSameType(other:SBigInt[T])={};
}
टेस्ट वाक्य रचना:
class CompileToTest {
val signed=new SInt[Signed](5);
val positive=new SInt[Positive](5);
val negative=new SInt[Negative](-5);
val zero=new SInt[Zero](0);
(signed + signed).assertSameType(signed);
(negative + signed).assertSameType(signed);
(positive - positive).assertSameType(signed);
(positive * negative).assertSameType(signed);
(zero + zero).assertSameType(zero);
val positiveDouble=SDouble[Positive](4.4)
val negativeDouble=SDouble[Negative](-4.4)
val signedDouble=SDouble[Signed](-4.4)
(positiveDouble * negativeDouble).assertSameType(signedDouble);
}
Ps। वास्तव में बाइटकोड को नहीं देखा है, लेकिन दस्तावेज़ों ने यह सुझाव दिया है कि इसे रेखांकित किया जाना चाहिए और प्राइमेटिव्स को संकलित किया जाना चाहिए।
मुझे बस इस लेन-देन से प्यार है।
तो मैंने इस दृष्टिकोण को लेने के बारे में सोचा - ओकम्ल अपने मॉड्यूल में हर समय इसका उपयोग करता है। '+', '-',' * 'जैसी चीज़ों पर हस्ताक्षर कैसे कार्यान्वित करेंगे? क्या आपके पास उन सभी कार्यों के लिए 'ए' प्रकार वापस किया जाएगा? इससे सवाल उठता है कि अंत उपयोगकर्ता वास्तव में अंतर्निहित प्रकार का उपयोग कैसे करता है? कुछ फ़ंक्शन (ए: ए): <अंतर्निहित प्रकार यहां>? –
क्या सार्वजनिक दायरे में 'अंतर्निहित' होने से टाइप इंकैप्यूलेशन कमजोर पड़ता है? मैं बाड़ पर हूं मुझे लगता है ... –
कुछ और विचारों के साथ संपादित किया गया। मुझे लगता है कि आपको यह तय करना होगा कि क्या आप अंतर्निहित प्रकार/मूल्य का खुलासा करना चाहते हैं या नहीं। मुझे लगता है कि आप विरासत का उपयोग करने के बजाय 'संख्या' प्रकार वर्ग बनाने पर भी विचार कर सकते हैं। –