throw new Exception(s"$x is too big for Int")
The expression beginning with "$" is replaced in the string by its value (in this case the evaluating x, whether that is a function or an identifier). Expressions including spaces require curly braces. If you follow the link referenced at the top, you will see how to customize string interpolation for your own purposes. If it is all completely clear to you by the time you get back here, then just ignore the rest of this blog post.
But if, like me, you find that comments like "A simple (buggy) implementation of this method could be:..." less than super-helpful, then stay right here and see a real example.
The example I'm going to present is the creation of a Rational number using the string form r"n/d" where n and d represent the numerator and denominator respectively. What Rational, I hear you say—there is no Rational object in Scala. Well, that's true (today at least). But we are going to suppose that we do have the following class (where most of the code in the middle has been replaced by ellipsis).
case class Rational(n: Long, d: Long) extends Numeric[Rational] { ... } object Rational { def apply(x: Long): Rational = new Rational(x,1) def apply(x: String): Rational = { val rRat = """^\s*(\d+)\s*(\/\s*(\d+)\s*)?$""".r x match { case rRat(n,_,d) => Rational(n.toLong,d.toLong) case rRat(n) => Rational(n.toLong) case _ => throw new Exception(s"invalid rational expression: $x") } } ... }
We will add the code described in the linked document to the object definition above. However, we will have to work the actual implementation a little better.
object Rational { implicit class RationalHelper(val sc: StringContext) extends AnyVal { def r(args: Any*): Rational = { val strings = sc.parts.iterator val expressions = args.iterator val sb = new StringBuffer() while(strings.hasNext) { val s = strings.next if (s.isEmpty) { if(expressions.hasNext) sb.append(expressions.next) else throw new Exception("r: logic error: missing expression") } else sb.append(s) } if(expressions.hasNext) throw new Exception(s"r: logic error: ignored: ${expressions.next}") else Rational(sb.toString) } } ... }
You can probably eliminate the rather ugly logic errors because I don't think they can ever happen (although the mechanism which requires you to evaluate the next expression when you get an empty argument string is rather hokey and not well explained).
That's all there is to it. If you actually want to use it in another class file, then you will need to import Rational.RationalHelper.
No comments:
Post a Comment