Scala by Luc Duponcheel
- 13. Function result
scala> :l plus.scala
Loading plus.scala...
plus: (x: Int)(Int) => Int
scala> plus(1)
res0: (Int) => Int = <function1>
- 16. Function parameter
scala> :l applyToZero.scala
Loading applyToZero.scala...
applyToZero: [X]((Int) => X)X
scala> applyToZero (x => x + 1)
res0: Int = 1
- 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
- 20. Function parameter and result
scala> :l twiceMany.scala
Loading twiceMany.scala...
twice: [X](f: (X) => X)(x: X)X
scala> twice((x: Int) => x + 1)(0)
res0: Int = 2
- 21. Placeholder syntax
scala> :l applyToZero.scala
Loading applyToZero.scala...
applyToZero: [X]((Int) => X)X
scala> applyToZero (_ + 1)
res0: Int = 1
- 26. Using structural recursion
def sumOfDigits =
structRec[Int](0, _ + _)
def hasDigit(d: Dig) =
structRec[Boolean](false, _ == d || _)
def exists(p: Dig => Boolean) =
structRec[Boolean](false, p(_) || _)
- 27. Using structural recursion
scala> sumOfDigits(1234)
res0: Int = 10
scala> hasDigit(2)(1234)
res1: Boolean = true
scala> exists(_ == 2)(1234)
res2: Boolean = true
- 28. unfoldAndThenFold
6
---- | / |
| dig = 3 + 3 = rec |
-----------------------
| 2 + 1 |
| / |
| 1 + 0 |
| / |
| 0 0 |
- 31. Tail recursion
def tailRec[A]
(a: A, op: (Dig, A) => A) : Nat => A = {
(n: Nat) =>
if(n == 0) {
a
} else {
tailRec(op(n % 10, a), op)(n / 10)
}
}
- 32. Using tail recursion
def sumOfDigits =
tailRec[Int](0, _ + _)
def hasDigit(d: Dig) =
tailRec[Boolean](false, _ == d || _)
def exists(p: Dig => Boolean) =
tailRec[Boolean](false, p(_) || _)
- 33. Using tail recursion
scala> sumOfDigits(1234)
res0: Int = 10
scala> hasDigit(2)(1234)
res1: Boolean = true
scala> exists(_ == 2)(1234)
res2: Boolean = true
- 34. iterateAndAccumulate
6 = rec
| / |
| 0 6 |
| / |
| 1 + 5 |
| ------------
| 2| + 3 = acc |
--------| / |
| dig = 3 + 0 |
- 39. Loop expression
scala> :l while.scala
Loading while.scala...
_while: (() => Boolean)(() => Unit)Unit
scala> _while(() => Math.random<0.5)(() =>
| println ("ok")
| )
ok
- 43. Loop expression
scala> :l while_cbn.scala
Loading while_cbn.scala...
_while: (=> Boolean)(=> Unit)Unit
scala> _while(Math.random<0.5) {
| println ("ok")
| }
ok
- 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
- 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
- 67. Put and Reg
case class Put[X](x: X)
case class Reg[X](
work: Work[X]
worker: Worker[X])
- 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
- 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
}
}
- 89. thePlayers
val thePlayers =
Pinger("pinger_1", true) ::
Pinger("pinger_2", false) ::
Ponger("ponger_1") ::
Ponger("ponger_2") ::
Nil