Sample run of chapter's interpreter examples
// In file abstract-members/AbsConc.scala trait Abstract { type T def transform(x: T): T val initial: T var current: T }
// In file abstract-members/AbsConc.scala class Concrete extends Abstract { type T = String def transform(x: String) = x + x val initial = "hi" var current = initial }
val initial: String
val initial = "hi"
def initial: String
// In file abstract-members/DefOverVal.scala.err abstract class Fruit { val v: String // `v' for value def m: String // `m' for method } abstract class Apple extends Fruit { val v: String val m: String // OK to override a `def' with a `val' } abstract class BadApple extends Fruit { def v: String // ERROR: cannot override a `val' with a `def' def m: String }
// In file abstract-members/AbstractTime.scala trait AbstractTime { var hour: Int var minute: Int }
// In file abstract-members/AbstractTime.scala trait AbstractTime { def hour: Int // getter for `hour' def hour_=(x: Int): Unit // setter for `hour' def minute: Int // getter for `minute' def minute_=(x: Int): Unit // setter for `minute' }
// In file abstract-members/Misc.scala trait RationalTrait { val numerArg: Int val denomArg: Int }
// In file abstract-members/Misc.scala new RationalTrait { val numerArg = 1 val denomArg = 2 }
new Rational(expr1, expr2)
// In file abstract-members/Misc.scala new RationalTrait { val numerArg = expr1 val denomArg = expr2 }
// In file abstract-members/Misc.scala trait RationalTrait { val numerArg: Int val denomArg: Int require(denomArg != 0) private val g = gcd(numerArg, denomArg) val numer = numerArg / g val denom = denomArg / g private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) override def toString = s"numer/denom" }
scala> val x = 2 x: Int = 2 scala> new RationalTrait { | val numerArg = 1 * x | val denomArg = 2 * x | } java.lang.IllegalArgumentException: requirement failed at scala.Predef$.require(Predef.scala:280) at RationalTrait.$init$(<console>:4) ... 28 elided
scala> new { | val numerArg = 1 * x | val denomArg = 2 * x | } with RationalTrait res1: RationalTrait = 1/2
// In file abstract-members/Misc.scala object twoThirds extends { val numerArg = 2 val denomArg = 3 } with RationalTrait
// In file abstract-members/Misc.scala class RationalClass(n: Int, d: Int) extends { val numerArg = n val denomArg = d } with RationalTrait { def + (that: RationalClass) = new RationalClass( numer * that.denom + that.numer * denom, denom * that.denom ) }
scala> new { | val numerArg = 1 | val denomArg = this.numerArg * 2 | } with RationalTrait On line 3: error: value numerArg is not a member of object $iw val denomArg = this.numerArg * 2 ^
scala> object Demo { | val x = { println("initializing x"); "done" } | } defined object Demo
scala> Demo initializing x res3: Demo.type = Demo$@2129a843 scala> Demo.x res4: String = done
scala> object Demo { | lazy val x = { println("initializing x"); "done" } | } defined object Demo scala> Demo res5: Demo.type = Demo$@1a18e68a scala> Demo.x initializing x res6: String = done
trait LazyRationalTrait { val numerArg: Int val denomArg: Int lazy val numer = numerArg / g lazy val denom = denomArg / g override def toString = s"numer/denom" private lazy val g = { require(denomArg != 0) gcd(numerArg, denomArg) } private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) }
scala> val x = 2 x: Int = 2 scala> new LazyRationalTrait { | val numerArg = 1 * x | val denomArg = 2 * x | } res7: LazyRationalTrait = 1/2
// In file abstract-members/BuggyAnimals.scala.err class Food abstract class Animal { def eat(food: Food): Unit }
// In file abstract-members/BuggyAnimals.scala.err class Grass extends Food class Cow extends Animal { override def eat(food: Grass) = {} // This won't compile }
BuggyAnimals.scala:7: error: class Cow needs to be abstract, since method eat in class Animal of type (Food)Unit is not defined class Cow extends Animal { ^ BuggyAnimals.scala:8: error: method eat overrides nothing override def eat(food: Grass) = {} ^
class Food abstract class Animal { def eat(food: Food): Unit } class Grass extends Food class Cow extends Animal { override def eat(food: Grass) = {} // This won't compile, } // but if it did,... class Fish extends Food val bessy: Animal = new Cow bessy eat (new Fish) // ...you could feed fish to cows.
// In file abstract-members/Animals.scala class Food abstract class Animal { type SuitableFood <: Food def eat(food: SuitableFood): Unit }
// In file abstract-members/Animals.scala class Grass extends Food class Cow extends Animal { type SuitableFood = Grass override def eat(food: Grass) = {} }
scala> class Fish extends Food defined class Fish scala> val bessy: Animal = new Cow bessy: Animal = Cow@4df50829 scala> bessy eat (new Fish) ^ error: type mismatch; found : Fish required: bessy.SuitableFood
class DogFood extends Food class Dog extends Animal { type SuitableFood = DogFood override def eat(food: DogFood) = {} }
scala> val bessy = new Cow bessy: Cow = Cow@6740b169 scala> val lassie = new Dog lassie: Dog = Dog@31419d4a scala> lassie eat (new bessy.SuitableFood) ^ error: type mismatch; found : Grass required: DogFood
scala> val bootsie = new Dog bootsie: Dog = Dog@2740c1e scala> lassie eat (new bootsie.SuitableFood)
// In file abstract-members/Misc.scala class Outer { class Inner }
val o1 = new Outer val o2 = new Outer
scala> new o1.Inner res11: o1.Inner = Outer$Inner@2e13c72b
scala> new Outer#Inner ^ error: Outer is not a legal prefix for a constructor
Animal { type SuitableFood = Grass }
// In file abstract-members/Animals.scala class Pasture { var animals: List[Animal { type SuitableFood = Grass }] = Nil // ... }
// In file abstract-members/Misc.scala object Color extends Enumeration { val Red = Value val Green = Value val Blue = Value }
// In file abstract-members/Misc.scala object Color extends Enumeration { val Red, Green, Blue = Value }
// In file abstract-members/Misc.scala import Color._
// In file abstract-members/Misc.scala object Direction extends Enumeration { val North, East, South, West = Value }
object Direction extends Enumeration { val North = Value("North") val East = Value("East") val South = Value("South") val West = Value("West") }
scala> for (d <- Direction.values) print(d + " ") North East South West
scala> Direction.East.id res14: Int = 1
scala> Direction(1) res15: Direction.Value = East
// In file abstract-members/Misc.scala // A first (faulty) design of the Currency class abstract class Currency { val amount: Long def designation: String override def toString = s"amount designation" def + (that: Currency): Currency = ... def * (x: Double): Currency = ... }
79 USD 11000 Yen 99 Euro
// In file abstract-members/Misc.scala new Currency { val amount = 79L def designation = "USD" }
// In file abstract-members/Misc.scala abstract class Dollar extends Currency { def designation = "USD" } abstract class Euro extends Currency { def designation = "Euro" }
// In file abstract-members/AbstractCurrency.scala.err // A second (still imperfect) design of the Currency class abstract class AbstractCurrency { type Currency <: AbstractCurrency val amount: Long def designation: String override def toString = s"amount designation" def + (that: Currency): Currency = ... def * (x: Double): Currency = ... }
abstract class Dollar extends AbstractCurrency { type Currency = Dollar def designation = "USD" }
// In file abstract-members/AbstractCurrency.scala.err def + (that: Currency): Currency = new Currency { val amount = this.amount + that.amount }
error: class type required def + (that: Currency): Currency = new Currency { ^
abstract class AbstractCurrency { type Currency <: AbstractCurrency // abstract type def make(amount: Long): Currency // factory method ... // rest of class }
myDollar.make(100) // here are a hundred more!
// In file abstract-members/Misc.scala abstract class CurrencyZone { type Currency <: AbstractCurrency def make(x: Long): Currency abstract class AbstractCurrency { val amount: Long def designation: String override def toString = s"amount designation" def + (that: Currency): Currency = make(this.amount + that.amount) def * (x: Double): Currency = make((this.amount * x).toLong) } }
// In file abstract-members/Misc.scala object US extends CurrencyZone { abstract class Dollar extends AbstractCurrency { def designation = "USD" } type Currency = Dollar def make(x: Long) = new Dollar { val amount = x } }
abstract class CurrencyZone { ... val CurrencyUnit: Currency }
// In file abstract-members/CurrencyZone.scala override def toString = ((amount.toDouble / CurrencyUnit.amount.toDouble) formatted ("%." + decimals(CurrencyUnit.amount) + "f") + " " + designation)
// In file abstract-members/CurrencyZone.scala object US extends CurrencyZone { abstract class Dollar extends AbstractCurrency { def designation = "USD" } type Currency = Dollar def make(cents: Long) = new Dollar { val amount = cents } val Cent = make(1) val Dollar = make(100) val CurrencyUnit = Dollar }
// In file abstract-members/CurrencyZone.scala private def decimals(n: Long): Int = if (n == 1) 0 else 1 + decimals(n / 10)
// In file abstract-members/CurrencyZone.scala def from(other: CurrencyZone#AbstractCurrency): Currency = make(math.round( other.amount.toDouble * Converter.exchangeRate (other.designation)(this.designation)))
// In file abstract-members/CurrencyZone.scala object Europe extends CurrencyZone { abstract class Euro extends AbstractCurrency { def designation = "EUR" } type Currency = Euro def make(cents: Long) = new Euro { val amount = cents } val Cent = make(1) val Euro = make(100) val CurrencyUnit = Euro } object Japan extends CurrencyZone { abstract class Yen extends AbstractCurrency { def designation = "JPY" } type Currency = Yen def make(yen: Long) = new Yen { val amount = yen } val Yen = make(1) val CurrencyUnit = Yen }
// In file abstract-members/Misc.scala object Converter { var exchangeRate = Map( "USD" -> Map("USD" -> 1.0 , "EUR" -> 0.7596, "JPY" -> 1.211 , "CHF" -> 1.223), "EUR" -> Map("USD" -> 1.316 , "EUR" -> 1.0 , "JPY" -> 1.594 , "CHF" -> 1.623), "JPY" -> Map("USD" -> 0.8257, "EUR" -> 0.6272, "JPY" -> 1.0 , "CHF" -> 1.018), "CHF" -> Map("USD" -> 0.8108, "EUR" -> 0.6160, "JPY" -> 0.982 , "CHF" -> 1.0 ) ) }
// In file abstract-members/Misc.scala abstract class CurrencyZone { type Currency <: AbstractCurrency def make(x: Long): Currency abstract class AbstractCurrency { val amount: Long def designation: String def + (that: Currency): Currency = make(this.amount + that.amount) def * (x: Double): Currency = make((this.amount * x).toLong) def - (that: Currency): Currency = make(this.amount - that.amount) def / (that: Double) = make((this.amount / that).toLong) def / (that: Currency) = this.amount.toDouble / that.amount def from(other: CurrencyZone#AbstractCurrency): Currency = make(math.round( other.amount.toDouble * Converter.exchangeRate (other.designation)(this.designation))) private def decimals(n: Long): Int = if (n == 1) 0 else 1 + decimals(n / 10) override def toString = ((amount.toDouble / CurrencyUnit.amount.toDouble) formatted ("%." + decimals(CurrencyUnit.amount) + "f") + " " + designation) } val CurrencyUnit: Currency }
scala> Japan.Yen from US.Dollar * 100 res16: Japan.Currency = 12110 JPY scala> Europe.Euro from res16 res17: Europe.Currency = 75.95 EUR scala> US.Dollar from res17 res18: US.Currency = 99.95 USD
scala> US.Dollar * 100 + res18 res19: US.Currency = 199.95 USD
scala> US.Dollar + Europe.Euro ^ error: type mismatch; found : Europe.Euro required: US.Currency (which expands to) US.Dollar
For more information about Programming in Scala, Fourth Edition (the "Stairway Book"), please visit: http://www.artima.com/shop/programming_in_scala_4ed and: |
Copyright © 2007-2019 Artima, Inc. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. |