I’m back to learning Scala. I’m starting with Rpn Calculator With Refactoring And Patterns . Here are a few examples of the code I’ve create. I’d appreciate feedback of any kind.
SpecTest looks nice as do Scala specs. I wanted a basic unit testing framework and it turns out the number of moving parts for Java is small, so I’m using it and I”ll be using scala specs for more rejection-check orientation.
RpnCalculatorShould.scala
package ex
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.CoreMatchers.is
import org.junit.Assert.assertThat
import org.junit.Before
import org.junit.Test
class RpnCalculatorShould {
var calculator : RpnCalculator = null
@Before
def init = {
calculator = new RpnCalculator
}
@Test
def addTwoNumbers = {
calculator . receive ( "3" )
calculator . receive ( "0" )
calculator . perform ( "enter" )
calculator . receive ( "4" )
calculator . perform ( "+" )
assertThat ( calculator . xRegister , is ( equalTo ( "34" )))
}
@Test
def subtractTwoNumbers = {
calculator . receive ( "3" )
calculator . receive ( "0" )
calculator . perform ( "enter" )
calculator . receive ( "4" )
calculator . perform ( "-" )
assertThat ( calculator . xRegister , is ( equalTo ( "26" )))
}
@Test
def calculateTheFactorialOf5As120 {
calculator . receive ( "5" )
calculator . perform ( "!" )
assertThat ( calculator . xRegister , is ( equalTo ( "120" )))
}
@Test
def calculateDivideCorrectly () {
calculator . receive ( "3" )
calculator . receive ( "0" )
calculator . perform ( "enter" )
calculator . receive ( "4" )
calculator . perform ( "/" )
assertThat ( calculator . xRegister , is ( equalTo ( "7.5" )))
}
@Test
def calculateMultiplyCorrectly () {
calculator . receive ( "3" )
calculator . receive ( "0" )
calculator . perform ( "enter" )
calculator . receive ( "4" )
calculator . perform ( "*" )
assertThat ( calculator . xRegister , is ( equalTo ( "120" )))
}
}
MathOperator.scala
package ex
abstract class MathOperator {
def apply ( values : RpnStack )
}
BinaryMathOperator.scala
package ex
import java.math.BigDecimal
class BinaryOperator ( private val expression : ( BigDecimal , BigDecimal ) => BigDecimal ) extends MathOperator {
def apply ( values : RpnStack ) = {
val rhs = values . pop
val lhs = values . pop
values push expression ( lhs , rhs )
}
}
RealOperatorFactory.scala
package ex
object RealMathOperatorFactory extends MathOperatorFactory {
var operatorsByName = Map [ String , MathOperator ](
"enter" -> new Enter ,
"+" -> new BinaryOperator (( lhs , rhs ) => lhs . add ( rhs )),
"-" -> new BinaryOperator (( lhs , rhs ) => lhs . subtract ( rhs )),
"!" -> new Factorial ,
"/" -> new BinaryOperator (( lhs , rhs ) => lhs . divide ( rhs )),
"*" -> new BinaryOperator (( lhs , rhs ) => lhs . multiply ( rhs )))
def apply ( operatorName : String ) = operatorsByName ( operatorName )
}
RpnCalculator.scala
package ex
import java.math.BigDecimal
class RpnCalculator ( private val factory : MathOperatorFactory ) {
def this () = this ( RealMathOperatorFactory )
val values = new RpnStack
def receive ( number : String ) = {
var current = values . pop . toPlainString
current += number
values push new BigDecimal ( current )
}
def perform ( operatorName : String ) = factory ( operatorName )( values )
def xRegister () = values . top . toPlainString
}
RpnStack.scala
package ex
import java.math.BigDecimal
import scala.collection.mutable.Stack
class RpnStack {
def pop () = if ( values . size > 0 ) values pop else BigDecimal . ZERO
def top () = if ( values . size > 0 ) values top else BigDecimal . ZERO
def push ( number : BigDecimal ) = values push number
def size () = values size
val values = Stack [ BigDecimal ]();
}
Comments