Permalink
Browse files

Reverted the incomplete work on 10 m/s -style markup, old 10*m/s -sty…

…le markup is used instead.

Added function to get basic unit exponent values for a known unit.
Fixed compile error, turns out one can not create instances of nested type references or something like that, and the compiler crashes if one tries to ( https://groups.google.com/group/scala-user/browse_thread/thread/7861789d4aa7c0b8 ).
Wrote scalatest with some testcases, removed junit dependency.
Updated scala version to newest stable (2.9.1-1).
  • Loading branch information...
1 parent 515461d commit bc77360c40668917f7b9fff2c5f9c23be0c9ba1d @zzorn committed Apr 10, 2012
View
14 pom.xml
@@ -7,8 +7,8 @@
<!-- Some main library version properties -->
<properties>
- <scala.version>2.8.0.RC5</scala.version>
- <scalatest.version>1.2-for-scala-2.8.0.RC3-SNAPSHOT</scalatest.version>
+ <scala.version>2.9.1</scala.version>
+ <scalatest.version>1.7.1</scalatest.version>
<projectversion>0.3-SNAPSHOT</projectversion>
<projectname>scalaquantity</projectname>
<projectfile>${projectname}-${projectversion}</projectfile>
@@ -50,6 +50,7 @@
<url>http://www.scala-tools.org/repo-snapshots</url>
</repository>
+
</repositories>
<!-- Places to retrieve maven plugins from -->
@@ -73,18 +74,11 @@
<!-- Testing -->
<dependency>
<groupId>org.scalatest</groupId>
- <artifactId>scalatest</artifactId>
+ <artifactId>scalatest_${scala.version}</artifactId>
<version>${scalatest.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.8.1</version>
- <scope>test</scope>
- </dependency>
-
<!-- Scala -->
<dependency>
<groupId>org.scala-lang</groupId>
@@ -1,6 +1,7 @@
package scalaquantity
-import scalaquantity.Utils.TypeToValue
+
+
object Exponents {
@@ -26,6 +27,7 @@ object Exponents {
type Prev = Next#Neg
}
+
sealed trait PosExp extends NatExp
final class NextExp[P <: NatExp] extends PosExp {
type This = NextExp[P]
@@ -71,20 +73,17 @@ object Exponents {
type N9 = P9#Neg
type N10 = P10#Neg
- val P0 = new P0
- val P1 = new P1
- val P2 = new P2
- val P3 = new P3
- val P4 = new P4
- val P5 = new P5
- val P6 = new P6
- val P7 = new P7
- val P8 = new P8
- val P9 = new P9
- val P10 = new P10
-
- implicit val p0ToInt = TypeToValue[P0, Int](0)
- implicit def nextToInt[P <: NatExp](implicit v : TypeToValue[P, Int]) = TypeToValue[NextExp[P], Int](1 + v.value)
- implicit def negToInt[P <: PosExp](implicit v : TypeToValue[P, Int]) = TypeToValue[NegExp[P], Int](-v.value)
+
+ case class ExponentToValue[T](value : Int)
+ implicit val p0ToInt = ExponentToValue[P0](0)
+ implicit def nextToInt[P <: NatExp](implicit v : ExponentToValue[P]) = ExponentToValue[NextExp[P]]( 1 + v.value )
+ implicit def negToInt [P <: PosExp](implicit v : ExponentToValue[P]) = ExponentToValue[NegExp[P] ]( -v.value )
+
+ /**
+ * @return the integer value of the specified unit exponent.
+ * E.g. exponentValue[Speed#M] == 1 and exponentValue[Speed#S] == -1
+ */
+ def exponentValue[T](implicit exponentToValue: ExponentToValue[T]): Int = exponentToValue.value
+
}
@@ -3,7 +3,6 @@ package scalaquantity
import Exponents._
import scala.math.Pi
-// TODO: Add an implicit conversation from ints and doubles to a UnitfulNumber, that has methods such as m, cm, km, etc. to create quantities -> natural syntax
object Units {
@@ -21,7 +20,7 @@ object Units {
}
type / [A <: Unit, B <: Unit] = A#Div[B]
- type ~ [A <: Unit, B <: Unit] = A#Mul[B] // We can not use * as a type, because it is reseved for variable length argument lists
+ type ~ [A <: Unit, B <: Unit] = A#Mul[B] // We can not use * as a type, because it is reserved for variable length argument lists
case class Quantity[M_ <: Exp, KG_ <: Exp, S_ <: Exp, A_ <: Exp, K_ <: Exp, Mol_ <: Exp, CD_ <: Exp](value: Double = 1.0) extends Unit {
type M = M_
@@ -37,14 +36,16 @@ object Units {
def -(m : This) = Quantity[M, KG, S, A, K, Mol, CD](value - m.value)
def *[M2 <: Exp, KG2 <: Exp, S2 <: Exp, A2 <: Exp, K2 <: Exp, Mol2 <: Exp, CD2 <: Exp](m : Quantity[M2, KG2, S2, A2, K2, Mol2, CD2]) = Quantity[M + M2, KG + KG2, S + S2, A + A2, K + K2, Mol + Mol2, CD + CD2](value * m.value)
def /[M2 <: Exp, KG2 <: Exp, S2 <: Exp, A2 <: Exp, K2 <: Exp, Mol2 <: Exp, CD2 <: Exp](m : Quantity[M2, KG2, S2, A2, K2, Mol2, CD2]) = Quantity[M - M2, KG - KG2, S - S2, A - A2, K - K2, Mol - Mol2, CD - CD2](value / m.value)
-
- // def apply(v : Double) = Quantity[M, KG, S, A, K, Mol, CD](v * value)
+
+ def apply(v : Double) = Quantity[M, KG, S, A, K, Mol, CD](v * value)
override def toString = "" + value
}
implicit def measure(v : Double) = Quantity[__, __, __, __, __, __, __](v)
+ implicit def unitlessQuantityToDouble(q: Quantity[__, __, __, __, __, __, __]): Double = q.value
+
// Unitless quantity
type One = Quantity[__, __, __, __, __, __, __];
@@ -159,7 +160,7 @@ object Units {
// Unitless values (angles)
val unitlessOne = new One()
-/*
+
/** Unit of radians. E.g. 2*Pi*radians = 360 degrees. */
val rad = new rad()
val Trad = rad(tera)
@@ -170,51 +171,7 @@ object Units {
val urad = rad(micro)
val nrad = rad(nano)
val prad = rad(pico)
-*/
-
- // Length
- /** meter (unit of length) */
- val m = new m()
- val meter = m
- val Tm = tera m
- val Gm = giga m
- val Mm = mega m
- val km = kilo m
- val dm = deci m
- val cm = centi m
- val mm = milli m
- val um = micro m
- val nm = nano m
- val pm = pico m
-
- // Mass
- /** gram (0.01 of unit of mass) */
-/*
- val g = new kg(1e-3)
- val gram = g
- val Tg = tera*g
- val Gg = giga*g
- val Mg = mega*g
- val kg = kilo*g
- val mg = milli*g
- val ug = micro*g
- val ng = nano*g
- val pg = pico*g
-*/
- // Time
- /** second (unit of time) */
- val s = new s()
- val second = s
- val Ts = tera s
- val Gs = giga s
- val Ms = mega s
- val ks = kilo s
- val ms = milli s
- val us = micro s
- val ns = nano s
- val ps = pico s
-/*
// Length
/** meter (unit of length) */
val m = new m()
@@ -577,17 +534,17 @@ object Units {
val L = litre
/** Minute (60 seconds)*/
- val min = s(60)
+ val min = 60*s
/** Hour (60 minutes)*/
val h = min(60)
/** Day (24 hours)*/
val day = h(24)
/** Julian year, defined as 365.25 days. */
val year = day(365.25)
- /** bar (non-standard unit of pressure) = 10^5 Pa.*/
+ /** bar (non-standard unit of pressure) = 100 kPa.*/
val bar = Pa(1e5)
- /** millibar (non-standard unit of pressure) = 10^2 Pa.*/
+ /** millibar (non-standard unit of pressure) = 100 Pa.*/
val mbar = hPa
/** atmosphere (non-standard unit of pressure) = 1013.25 mbar.*/
val atm = mbar(1013.25)
@@ -638,95 +595,8 @@ object Units {
val pound = ounce(16)
val pounds = pound
val lb = pound
-*/
-
-// Is there some way to get expressions like val foo = 10 m/s to work?
-
- implicit def intToQuantity(v: Int): QuantifiedNumber = QuantifiedNumber(v)
- implicit def doubleToQuantity(v: Double): QuantifiedNumber = QuantifiedNumber(v)
-
-
-/*
- type kgDiv = UnitDivisionNumerator[__,P1,__,__,__,__,__]
- type kgMul = UnitMultiplicationFactor[__,P1,__,__,__,__,__]
-*/
-
- case class QuantifiedNumber(v: Double) {
-
- def m: m = Units.m * v
- def s: s = Units.s * v
-/*
- def g: kg = Units.g * v
- def kg: kg = Units.kg * v
-*/
-
- def m(mark: UnitDiv): UnitDivisionNumerator[P1,__,__,__,__,__,__] = UnitDivisionNumerator[P1,__,__,__,__,__,__](Units.m)
- def m(mark: UnitMul): UnitMultiplicationFactor[P1,__,__,__,__,__,__] = UnitMultiplicationFactor[P1,__,__,__,__,__,__](Units.m)
-
-/* def Tg(mark: UnitDiv): kgDiv = new kgDiv(Units.Tg)
- def Gg(mark: UnitDiv): kgDiv = new kgDiv(Units.Gg)
- def Mg(mark: UnitDiv): kgDiv = new kgDiv(Units.Mg)
-
- def kg(mark: UnitDiv): kgDiv = new kgDiv(Units.kg)
- def mg(mark: UnitDiv): kgDiv = new kgDiv(Units.mg)
- def ug(mark: UnitDiv): kgDiv = new kgDiv(Units.ug)
- def ng(mark: UnitDiv): kgDiv = new kgDiv(Units.ng)
- def pg(mark: UnitDiv): kgDiv = new kgDiv(Units.pg)
-
- def Tg(mark: UnitMul): kgMul = new kgMul(Units.Tg)
- def Gg(mark: UnitMul): kgMul = new kgMul(Units.Gg)
- def Mg(mark: UnitMul): kgMul = new kgMul(Units.Mg)
- def kg(mark: UnitMul): kgMul = new kgMul(Units.kg)
- def mg(mark: UnitMul): kgMul = new kgMul(Units.mg)
- def ug(mark: UnitMul): kgMul = new kgMul(Units.ug)
- def ng(mark: UnitMul): kgMul = new kgMul(Units.ng)
- def pg(mark: UnitMul): kgMul = new kgMul(Units.pg)
-*/
-
- def s(mark: UnitDiv): UnitDivisionNumerator[__,__,P1,__,__,__,__] = UnitDivisionNumerator[__,__,P1,__,__,__,__](Units.s)
- def s(mark: UnitMul): UnitMultiplicationFactor[__,__,P1,__,__,__,__] = UnitMultiplicationFactor[__,__,P1,__,__,__,__](Units.s)
-
- //def m[M <: Exp, KG <: Exp, S <: Exp, A <: Exp, K <: Exp, Mol <: Exp, CD <: Exp](q : Quantity[M,KG,S,A,K,Mol,CD]) = Units.m * q
-// def m[Q <: Quantity[Exp,Exp,Exp,Exp,Exp,Exp,Exp]](part: Q): m/Q = Units.m(v) / part
- }
-
- case class UnitDivisionNumerator[M <: Exp, KG <: Exp, S <: Exp, A <: Exp, K <: Exp, Mol <: Exp, CD <: Exp](q: Quantity[M,KG,S,A,K,Mol,CD]) {
- def m: Quantity[M,KG,S,A,K,Mol,CD]/m = q / Units.m
-/*
- def g: Quantity[M,KG,S,A,K,Mol,CD]/kg = q / Units.g
- def kg: Quantity[M,KG,S,A,K,Mol,CD]/kg = q / Units.kg
-*/
- def s: Quantity[M,KG,S,A,K,Mol,CD]/s = q / Units.s
- }
-
- case class UnitMultiplicationFactor[M <: Exp, KG <: Exp, S <: Exp, A <: Exp, K <: Exp, Mol <: Exp, CD <: Exp](q: Quantity[M,KG,S,A,K,Mol,CD]) {
- def m: Quantity[M,KG,S,A,K,Mol,CD]~m = q * Units.m
-/*
- def g: Quantity[M,KG,S,A,K,Mol,CD]~kg = q * Units.g
- def kg: Quantity[M,KG,S,A,K,Mol,CD]~kg = q * Units.kg
-*/
- def s: Quantity[M,KG,S,A,K,Mol,CD]~s = q * Units.s
- }
-
-
- sealed trait UnitDiv
- sealed trait UnitMul
- object UnitDivInstance extends UnitDiv
- object UnitMulInstance extends UnitMul
- val / = UnitDivInstance
- val * = UnitMulInstance
- //def /[M <: Exp, KG <: Exp, S <: Exp, A <: Exp, K <: Exp, Mol <: Exp, CD <: Exp](q: Quantity[M,KG,S,A,K,Mol,CD]):One/Quantity[M,KG,S,A,K,Mol,CD] = 1.0 / q
- //case class Division[Q <: Unit](quantity: Q)
- val foo1: s~m = 10 m*s
- val foo2: s/m = 10 s/m
- val foo3: m/s2 = 10.m/(s*s)
-// val foo4: kg/s = 10 kg / s
- val i = 1 / 2
- val j = i / i
- val k = m / i
- val l: One/m = i / m
+}
-}
@@ -2,24 +2,9 @@ package scalaquantity
object Utils {
- final class Invalid
trait SubType[T1 <: T2, T2]
trait Equal[T1 >: T2 <: T2, T2]
- class Fn1Wrapper[T1, R](fn : T1 => R) {
- def apply(a1 : T1) = fn(a1)
- }
- class Fn2Wrapper[T1, T2, R](fn : (T1, T2) => R) {
- def apply(a1 : T1, a2 : T2) = fn(a1, a2)
- }
-
- case class TypeToValue[T, VT](value : VT) {
- def apply() = value
- }
-
- def to[T, VT](implicit fn : TypeToValue[T, VT]) = fn()
-
- def value[T] : T = null.asInstanceOf[T]
}
@@ -4,13 +4,12 @@ import scalaquantity.Units._
import scala.math.Pi
/**
- * Tests units. If this compiles, then the test is successfull.
+ * Tests units. If this compiles, then the test is successful.
*/
object FoodExample {
def main(args: Array[String]) {
-/*
val appleRadius = 3*cm
val appleEnergyDensity = 52 * cal / (100*g)
val appleDensity = 1150 * kg/m3
@@ -20,8 +19,8 @@ object FoodExample {
println("Bob is stranded in a desert. He has one apple with a radius of "+appleRadius+" m and a density of " + appleDensity + " kg/m3\n" +
"Apples have an energy density of " + appleEnergyDensity + " J/kg.\n"+
- "Bob burns " + walkEnergy + " joules per meter when walking.\n" +
- "Bob walks at " + bobWalkSpeed + " m/s.\n" +
+ "Bob burns " + walkEnergy / (cal/mile) + " calories per mile when walking.\n" +
+ "Bob walks at " + bobWalkSpeed / (miles/h) + " miles/h.\n" +
"How far will Bob walk on the apple? How long?")
Thread.sleep(20000) // Dramatic pause!
@@ -33,8 +32,8 @@ object FoodExample {
val bobWalkDistance: Length = appleEnergy / walkEnergy
val bobWalkTime: Time = bobWalkDistance / bobWalkSpeed
- println("Bob will walk " + bobWalkDistance + " m for "+bobWalkTime/min+" min on the " +appleEnergy +" J of energy in the "+appleMass+" kg apple.")
-*/
+ println("Bob will walk " + bobWalkDistance / km + " km for "+bobWalkTime/min+" min on the " +appleEnergy +" J of energy in the "+appleMass/g+" g apple.")
+
}
}
Oops, something went wrong.

0 comments on commit bc77360

Please sign in to comment.