Skip to content
This repository has been archived by the owner on Sep 20, 2020. It is now read-only.

Commit

Permalink
updated sample Scala classes
Browse files Browse the repository at this point in the history
  • Loading branch information
smartiniOnGitHub committed Apr 8, 2014
1 parent fb36df6 commit 387fe98
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 8 deletions.
3 changes: 2 additions & 1 deletion docs/TODO.md
Expand Up @@ -7,9 +7,10 @@ TODO
- for next release 2.10.4:
- update to Scala-2.10.4 ... ok
- add some Scala test class (normal, case, object, trait, abstract, etc) to ensure that Scala code is compiled ... ok
- run ScalaDoc on Scala sources and see what happens (and fix something, if needed) ...
- test webapp: use sample classes (Scala) defined in the plugin, but from Groovy (using the Java interoperability way) ...
- add ScalaTest and make some tests using it ... ok, but only in the test webapp, and note that the aren't used in Grails test-app command
- verify at runtime, if it's enough to have only scala-runtime, and not scala-compiler ... the compiler is needed to build Scala sources
- verify at runtime, if it's enough to have only scala-runtime, and not scala-compiler ... no, the compiler is needed to build Scala sources
- SCALA_LICENSE, verify if it's right to have it there (but in a subfolder), or if move in root in other license-related files ... ok
- update Groovy doc files ... ok

Expand Down
68 changes: 61 additions & 7 deletions src/scala/grails_scala_test/Rational.scala
Expand Up @@ -35,6 +35,7 @@ package grails_scala_test
* Note that in this implementation, internal variables are defined lazy, just for sample.
*
*/
// TODO: in future verify if generalize to subclass of Number ...
class Rational(p: Int, q: Int) {
require(q != 0)

Expand Down Expand Up @@ -63,17 +64,42 @@ class Rational(p: Int, q: Int) {
def / (other: Rational) = new Rational(num * other.den, den * other.num)
def / (i: Int) = new Rational(num, den * i)

/** Return a normalized (reduced to minimum values) version of the current rational. */
def normalize() = if (den < 0) new Rational(-num, -den) else new Rational(num, den)
def < (other: Rational) = num * other.den < den * other.num
def < (i: Int) = num < den * i

def > (other: Rational) = num * other.den > den * other.num
def > (i: Int) = num > den * i

/** Check if it's equal to the given Rational. */
def ==(other: Rational) = num * other.den == den * other.num

/** Return a normalized (reduced to minimum values) version of the current rational. */
def normalize() = if (den < 0) new Rational(-num, -den) else new Rational(num, den)

/** Check if it's not equal to the given Rational. */
def !=(other: Rational) = ! ==(other)

/** Return the negative of the current rational (or multiplicated by -1). */
def negative() = new Rational(-p, q)

/** Return the inverse of the current rational (or power -1). */
def inverse() = new Rational(q, p)

/** Return the power of the current rational.
*
* Note that if redefine operator "**" or "^" for this operation,
* to add parentheses to have the right precedence in expressions,
* this is the main reason to not re-defining them here (for more simplicity).
*/
def power(n: Int) = n match {
case e if n < 0 => new Rational(Math.pow(den, e.abs).toInt, Math.pow(num, e.abs).toInt)
case _ => new Rational(Math.pow(num, n).toInt, Math.pow(den, n).toInt)
}

/** Calculates the integer value of division, and the integer remainder, returning both as a tuple. */
def valueAsInt() = (num / den, num % den)

// TODO: add ordering methods ...
// TODO: add a valueAsDouble method that returns a tuple vector (Double value, Boolean exact) ... and test with 10/3, 1/2, 2/5, etc ...

}

Expand All @@ -89,11 +115,15 @@ class Rational(p: Int, q: Int) {
val r = new Rational(2, 5)
println(s"rational h = ${h}")
println(s"rational r = ${r}")
h > r // true
h < r // false
import RationalHelper._
println(s"2 * h = ${(2 * h)}")
println(s"h * h = ${(h * h)}")
println(s"2 * r = ${(2 * r)}")
println(s"r * r = ${(r * r)}")
val m12 = new Rational(1,-2)
m12.normalize // -1/2
val m24 = new Rational(-2,-4)
Expand All @@ -105,16 +135,40 @@ class Rational(p: Int, q: Int) {
h != m12 // true
h == m24 // true
h != m24 // false
h.power(0) // 1/1
h.power(1) == h // true
h.power(2) // 1/4
h.power(-2) // 4/1
r.power(2) // 4/25
r.power(-2) // 25/4
h.valueAsInt // (0,1)
val r58 = RationalHelper(5, 8)
val r13 = RationalHelper(1, 3)
val r42 = RationalHelper(4, 2)
val r103 = RationalHelper(10, 3)
r103.valueAsInt // (3,1)
// etc ...
* }}}
*
*/
object RationalHelper {
import scala.language.implicitConversions
// import scala.language.postfixOps

implicit def int2Rational(x: Int) = new Rational(x)

// TODO: add implicit methods even for long2Rational, double2Rational ...
implicit def long2Rational(x: Long) = new Rational(x.toInt)

// TODO: add implicit methods even for double2Rational (scaling it by its decimals) ...
// TODO: check if add even rational2Int and rational2Double ...

/** Syntactic sugar for creating new Rational instances, without the need to use the new operator. */
def apply(p: Int, q: Int) = new Rational(p, q)

// / ** Syntactic sugar for deconstructing Rational instances in a tuple. * /
// def unapply(r: Rational) = (r.num, r.den)

/** Calculates the Greatest Common Divisor. */
def gcd(p: Int, q: Int): Int = if (q == 0) p else gcd(q, p % q)

Expand All @@ -123,9 +177,9 @@ object RationalHelper {

// TODO: generalize gcd, lcm methods for *Int ...

// TODO: add a valueAsInt method that returns a tuple vector (int value, int remind) ... and test with 10/3, 1/2, 2/5, etc ...
// TODO: add a valueAsDouble method that returns a tuple vector (Double value, Boolean exact) ... and test with 10/3, 1/2, 2/5, etc ...

// def zero: Rational = new Rational(0)
lazy val zero: Rational = new Rational(0)
lazy val unit: Rational = new Rational(1)

/** Sample for a Not Implemented method. */
def notImplemented(): Unit = ???
Expand Down

0 comments on commit 387fe98

Please sign in to comment.