Reputation: 1977
Scala has string interpolation like raw"\n"
for raw strings.
Does it have anything like number interpolation e.g. 1px
for one pixel? A nice syntax for numeric units would both make code more readable and make it easier to write safer code.
Like strings, numbers have a nice literal syntax and are fundamental.
prefix notation px(1)
is not how people write units:
case class px(n: Int)
And I don't think a postfix notation via implicit conversion can work:
case class Pixels(n: Int) {
def px() = Pixels(n)
def +(p: Pixels) = p match {case Pixels(m) => Pixels(n+m)}
}
implicit def Int2Pixels(n: Int) = Pixels(n)
it needs a dot or space or parens (i.e. not (1 px)
or (1)px
or 1.px
, which is not how humans write units).
it won't check types i.e. we want to explicitly cast between these numeric type-alias things and numbers themselves (i.e. 1.px + 2
and 1 + 2.px
and def inc(p: Pixels) = p + Pixels(1)
with inc(0)
all don't fail, because of the implicit cast, when they should).
Upvotes: 3
Views: 291
Reputation: 2769
You can define own string interpolation (more details here):
implicit class UnitHelper(val sc : StringContext) extends AnyVal {
def u(args: Any*): Pixels = {
val pxR = """(\d.*)\s*px""".r
sc.parts.mkString match {
case pxR(px) => Pixels(px.toInt)
case _ => throw new IllegalArgumentException
}
}
}
Usage example:
val x = u"10px" + u"20px" // x = Pixels(30)
Pros:
Cons:
Upvotes: 3
Reputation: 20415
Try the following implicit,
implicit def int2Pixels(n: Int) = new {
def px = Pixels(n)
}
Then
1 px
res: Pixels = Pixels(1)
Here we invoke the px
method on object 1
, a method that is not defined in Int
and so the implicit takes a role.
Altogether,
case class Pixels(n: Int) {
def px() = Pixels(n)
def +(p: Pixels) = p match {case Pixels(m) => Pixels(n+m)}
def +(m: Int) = Pixels(n+m)
}
// for enabling implicit conversion
import scala.language.implicitConversions
implicit def int2Pixels(n: Int) = new {
def px = Pixels(n)
}
and so
(12 px) + 1
res: Pixels = Pixels(13)
(12 px) + 1 px
res3: Pixels = Pixels(13)
For explanation on import see for instance Why implicitConversions is required for implicit defs but not classes? .
Upvotes: 1