Reputation: 3343
I'm currently working on Scala and getting surprised how good it is.
One of the great points I think is how it handles BigDecimal
type.Once defining a BigDecimal
You can use it almost as if it is Int
or Double
val foo:BigDecimal = 0.1
println(foo + 0.2) // 0.3
There is no need to use .multiply()
or .add()
but simply +
or *
to handle BigDecimal Calculation(I assume BigDecimal
's +
/*
end up calling them inside of it though).It's really easy to read even if a calculation gets complicated EXCEPT one thing that You have to declare first calculated value as BigDecimal
.
println(0.3 * (BigDecimal(0.1) + 0.2))
My question is, How Can I write above code like this?
println(0.3 * (0.1 + 0.2))
I assume that this requires to override numeric type literals.
Thanks in advance.
Upvotes: 3
Views: 155
Reputation: 369448
Scala doesn't allow overriding literals, unfortunately.
One thing you could easily do from within the language proper, would be to provide your own StringContext
for string interpolation:
implicit class BigDecimalStringContext(val sc: StringContext) extends AnyVal {
def d() = BigDecimal(sc.parts.head)
}
val test = d"0.1"
// => test: scala.math.BigDecimal = 0.1
I believe Macros don't allow you to override literals.
Scala-Virtualized is a fork of Scala, where (almost) everything (including control structures and object construction) translates into a method call and can thus be overloaded. Unfortunately, almost everything does not include overloading literals.
You might, however, be able to do something with a Compiler Plugin.
Upvotes: 2
Reputation: 14224
I don't think you can override numeric literals. What you can do is simplify the syntax a bit using string interpolation or adding methods to Double
.
// With string interpolation
implicit class BigDecimalStringContext(private val sc: StringContext) extends AnyVal {
def d(args: Any*): BigDecimal = {
val stringRepr = sc.s(args: _*)
BigDecimal(stringRepr)
}
}
println(d"0.3" * (d"0.1" + d"0.2"))
println(0.3 * (d"0.1" + 0.2))
// Pimp my library
implicit class DoubleOps(private val d: Double) extends AnyVal {
def bd = BigDecimal(d)
}
println(0.3.bd * (0.1.bd + 0.2.bd))
println(0.3 * (0.1.bd + 0.2))
The first method is safer, because the second one tries to convert a Double
, and thus may lose precision:
scala> 0.123456789012345678901234567890.bd * (0.1.bd + 0.2.bd)
res1: scala.math.BigDecimal = 0.037037036703703704
scala> d"0.123456789012345678901234567890" * (d"0.1" + d"0.2")
res2: scala.math.BigDecimal = 0.0370370367037037036703703703670
Upvotes: 6