18. Function parameter and result
scala> :l twice.scala
Loading twice.scala...
twice: [X]((X) => X)(X) => X
scala> twice((x: Int) => x + 1)(0)
res0: Int = 2
23. Compositional reuse
Compositional reuse is reuse of
code fragments
the building blocks, starting from atomic ones
code templates
the containers into which the building blocks
can be plugged
50. Class parameters: usage
scala> :l complex03.scala
Loading complex03.scala...
defined class C
scala> new C(-1, -1)
res0: C = -1.0 + -1.0*i
51. toString again
override def toString = {
val sgnim = if(im<0.0){" - "}else{" + "}
val absim = if(im<0.0){ -im }else{ im }
if(im == 0.0) { re + "" } else {
if(re == 0.0) { im + "*i" } else {
re + sgnim + absim + "*i" } }
}
52. toString again: usage
scala> :l complex04.scala
Loading complex04.scala...
defined class C
scala> new C(-1, -1)
res0: C = -1.0 - 1.0*i
scala> new C(-1, +1)
res1: C = -1.0 + 1.0*i
53. Additive operators
class C(r: Double, i: Double) {
// ...
def +(c: C) =
new C(re + c.re, im + c.im)
def -(c: C) =
new C(re - c.re, im - c.im)
// ...
}
54. Additive operators: usage
scala> :l complex05.scala
Loading complex05.scala...
defined class C
scala> new C(+1,+1) + new C(-3,+2)
res1: C = -2.0 + 3.0*i
scala> new C(+1,+1) - new C(-3,+2)
res2: C = 4.0 - 1.0*i
55. Multiplicative operators
// ...
def *(c: C) = new C(re*c.re - im*c.im,
im*c.re + re*c.im)
def /(c: C) = {
val d = c.re*c.re + c.im*c.im
new C((re*c.re + im*c.im) / d,
(im*c.re - re*c.im) / d) }
// ...
56. Multiplicative operators: usage
scala> :l complex06.scala
Loading complex06.scala...
defined class C
scala> new C(+1,+1) * new C(-3,+2)
res0: C = -5.0 - 1.0*i
scala> new C(-5,-1) / new C(-3,+2)
res1: C = 1.0 + 1.0*i
58. Negation operator: usage
scala> :l complex07.scala
Loading complex07.scala...
defined class C
scala> - new C(-5,-1)
res0: C = 5.0 + 1.0*i
scala> - new C(5,1)
res1: C = -5.0 - 1.0*i
59. The complex number i
class C(r: Double, i: Double) {
// ...
}
object C {
val i = new C(0.0, 1.0)
}
60. The complex number i: usage
scala> :l complex08.scala
Loading complex08.scala...
...
scala> import C.i
import C.i
scala> i * i
res0: C = -1.0
61. Converting Double
class C(r: Double, i: Double) {
// ...
}
object C {
//...
implicit def toC(d: Double)
= new C(d, 0.0)
}
62. Converting Double: usage
scala> :l complex09.scala
Loading complex09.scala...
...
scala> (1.0 + 1.0*i) / i
res0: C = 1.0 - 1.0*i
scala> 1.0 + 1.0*i / i
res1: C = 2.0
70. Space functionality: part one
A worker can put objects x into the space
using space ! Put(x)
A worker can register work with the space
using space ! Reg(work, worker)
71. Space functionality: part two
A space can notify a worker when an object
x, to which the work he registered with the
space can be applied, has been put into the
space using worker ! App(work, x)
72. reacting to a Put: part one
case p@Put(x: X) => {
val frs =
rs filter(r => r.work.isDefinedAt(x)
if(frs == Nil) {
ps ::= p.asInstanceOf[Put[X]]
}
73. reacting to a Put: part two
else {
val fr = frs.last
rs = rs filter (r => !(r eq fr))
fr.worker ! App(fr.work, x)
}
74. reacting to a Reg: part one
case r@Reg(work, worker) => {
val fps =
ps filter (p => work.isDefinedAt(p.x))
if(fps == Nil) {
rs ::= r.asInstanceOf[Reg[X]]
}
75. reacting to a Reg: part two
else {
val fp = fps.last
ps = ps filter (p => !(p eq fp))
worker ! App(work, fp.x)
}
76. Worker: part one
abstract class Worker[X](space: Space[X])
extends Actor {
protected var isAcceptingMoreWork = true
protected def registerForWork()
def put(x: X) {
space ! Put(x) }
def reg(work: Work[X]) {
space ! Reg(work, this) }
77. Worker: part two
private def applyZeroOrMoreTimes() {
loop { react {
case App(work, x) => {
work.apply(x)
if(isAcceptingMoreWork) {
registerForWork()
} } } }
}
80. PingPong
sealed abstract class PingPong
case object Ping extends PingPong
case object Pong extends PingPong
case object Over extends PingPong
case object Done extends PingPong
81. Player
abstract class Player(
name: String
table: Space[PingPong]
)
extends Worker[PingPong](table) {
override def toString = name
}
82. Pinger: part one
protected def registerForWork() =
reg {
case Pong => {
if (Math.random < 0.95) {
println(this + " ping")
put(Ping)
} else {
put(Over)
}
83. Pinger: part two
case Done => {
println(this + " stop")
isAcceptingMoreWork = false
}
}
}
}
84. Ponger: part one
protected def registerForWork() =
reg {
case Ping => {
if (Math.random < 0.95) {
println(this + " pong")
put(Pong)
} else {
put(Over)
}
85. Ponger: part two
case Done => {
println(this + " stop")
isAcceptingMoreWork = false
}
}
}
}
86. Umpire: part one
class Umpire(
name: String,
players: List[Player],
table: Space[PingPong])
extends Worker[PingPong](table) {
override def toString = name
87. Umpire: part two
protected def registerForWork() =
reg {
case Over => {
println(this + " done")
for { _ <- players } put(Done)
println(this + " stop")
isAcceptingMoreWork = false
}
}