PLACE specification programs about Scala

RPN Calculator in Scala

The program starts by creating a string variable s for storing input lines and a stack variable st where intermediate values go in the course of evaluating an RPN expression. The initial value for s, just like the initial values for x and y further in the text, are immaterial but required by the language's syntax.

The reading and processing of the input are performed in an ‘infinite’ loop. In fact the loop does end by calling exit upon detection of null instead of an actual string – signifying end-of-input – as the value of s.

In order to prepare for evaluating an expression stored in s, a tokenizer object tks is created on s, specifying whitespace characters as token delimiters. (The other argument in the call of SimpleTokenize is an array of the elements of the stripped off (trim) initial and trailing blanks version of s. Trimming is needed in order to avoid empty tokens.) tks can be seen as the stream of tokens that form the RPN expression, the individual elements of which are extracted by means of a for-comprehension – an abstract form of a sequence generator/utiliser.

A token tk is tried as a number at first. If it fails to parse as such, parseDouble raises an exception, and the catch part of the try statement reacts by checking whether tk is an operator character; if so, the corresponding operation is performed, provided there are arguments for it kept on the stack st. In case the latter does not hold, one of the two calls of pop fails with generating an exception.

A successfully processed token eventually leads to a value x, either directly read or computed, being pushed on the stack. For a token that is neither a number nor an operator, however, an exception is thrown explicitly. An exception is also raised if, after all the tokens successfully get processed, st happens to hold more than one number. Thus all kinds of syntax errors that may be there in an RPN expression result in an exception being raised. As the whole evaluation of an input line takes place within a try statement, any such exception is caught and handled by printing an error message instead of a numeric result.

Some of the names, defined in Scala's standard library and used in the program, are qualified by prefixing them by the corresponding package names. Others, namely readLine, println, exit and Error, are simple names. That is made possible by implicitly importing an object called Predef whose role is to provide a number of definitions, thus making possible to omit name qualifications. (There are two things happening here: first, (re-)exporting the names from Predef allows to use them with the Predef qualification instead of the original one. Second, the fact that Predef is imported makes even that qualification unnecessary.)

Note that, Scala being heavily Java-based, items of the latter language's library are directly being made use of as needed, even implicitly. Such is the case with the trim method in this program, which is really java.lang.String.trim. In fact, Scala's strings take all their functionality from those of Java. Also, parseDouble is indeed a Java's method, and so is referred to using an accordingly qualified name.

As given here, the program can be run by the Scala interpreter but not compiled. If a form suitable for compiling is needed, a couple of lines must be added that put an object context around the code.

var s = ""
var st = new scala.collection.mutable.Stack[Double]
while (true)  {
  s = readLine
  if (s==null)  exit
  val tks = new scala.util.parsing.SimpleTokenizer(s.trim.elements," \t")
  try  {
    for (val tk <- tks)  {
      var x = 0.;  var y = 0.
      try  {x = java.lang.Double.parseDouble(tk)}
      catch  {case _ =>  {
                y = st.pop;  x = st.pop
                tk match {case "+" => x += y  case "-" => x -= y
                          case "*" => x *= y  case "/" => x /= y
                          case _ => throw new Error}}}
      st.push(x)
    }
    if (st.length>1)  throw new Error
    if (!st.isEmpty)  println(st.pop)
  }
  catch  {case _ => {println("error"); st.clear}}
}

PLACE specification programs about Scala

boykobbatgmaildotcom