|     48 // some starting URLs for the crawler |     48 // some starting URLs for the crawler | 
|     49 val startURL = """https://nms.kcl.ac.uk/christian.urban/""" |     49 val startURL = """https://nms.kcl.ac.uk/christian.urban/""" | 
|     50 crawl(startURL, 2) |     50 crawl(startURL, 2) | 
|     51  |     51  | 
|     52  |     52  | 
|         |     53 // User-defined Datatypes | 
|         |     54 //======================== | 
|         |     55  | 
|         |     56  | 
|         |     57 abstract class Colour | 
|         |     58 case object Red extends Colour  | 
|         |     59 case object Green extends Colour  | 
|         |     60 case object Blue extends Colour | 
|         |     61  | 
|         |     62 def fav_colour(c: Colour) : Boolean = c match { | 
|         |     63   case Red   => false | 
|         |     64   case Green => true | 
|         |     65   case Blue  => false  | 
|         |     66 } | 
|         |     67  | 
|         |     68 fav_colour(Green) | 
|         |     69  | 
|         |     70  | 
|         |     71 // ... a tiny bit more useful: Roman Numerals | 
|         |     72  | 
|         |     73 abstract class RomanDigit  | 
|         |     74 case object I extends RomanDigit  | 
|         |     75 case object V extends RomanDigit  | 
|         |     76 case object X extends RomanDigit  | 
|         |     77 case object L extends RomanDigit  | 
|         |     78 case object C extends RomanDigit  | 
|         |     79 case object D extends RomanDigit  | 
|         |     80 case object M extends RomanDigit  | 
|         |     81  | 
|         |     82 type RomanNumeral = List[RomanDigit]  | 
|         |     83  | 
|         |     84 List(X,I) | 
|         |     85  | 
|         |     86 /* | 
|         |     87 I -> 1 | 
|         |     88 II -> 2 | 
|         |     89 III  -> 3 | 
|         |     90 IV -> 4 | 
|         |     91 V -> 5 | 
|         |     92 VI -> 6 | 
|         |     93 VII -> 7 | 
|         |     94 VIII -> 8 | 
|         |     95 IX -> 9 | 
|         |     96 X -> X | 
|         |     97 */ | 
|         |     98  | 
|         |     99 def RomanNumeral2Int(rs: RomanNumeral): Int = rs match {  | 
|         |    100   case Nil => 0 | 
|         |    101   case M::r    => 1000 + RomanNumeral2Int(r)   | 
|         |    102   case C::M::r => 900 + RomanNumeral2Int(r) | 
|         |    103   case D::r    => 500 + RomanNumeral2Int(r) | 
|         |    104   case C::D::r => 400 + RomanNumeral2Int(r) | 
|         |    105   case C::r    => 100 + RomanNumeral2Int(r) | 
|         |    106   case X::C::r => 90 + RomanNumeral2Int(r) | 
|         |    107   case L::r    => 50 + RomanNumeral2Int(r) | 
|         |    108   case X::L::r => 40 + RomanNumeral2Int(r) | 
|         |    109   case X::r    => 10 + RomanNumeral2Int(r) | 
|         |    110   case I::X::r => 9 + RomanNumeral2Int(r) | 
|         |    111   case V::r    => 5 + RomanNumeral2Int(r) | 
|         |    112   case I::V::r => 4 + RomanNumeral2Int(r) | 
|         |    113   case I::r    => 1 + RomanNumeral2Int(r) | 
|         |    114 } | 
|         |    115  | 
|         |    116 RomanNumeral2Int(List(I,V))             // 4 | 
|         |    117 RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid Roman number) | 
|         |    118 RomanNumeral2Int(List(V,I))             // 6 | 
|         |    119 RomanNumeral2Int(List(I,X))             // 9 | 
|         |    120 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 | 
|         |    121 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017 | 
|         |    122  | 
|         |    123  | 
|         |    124 // another example | 
|         |    125 //================= | 
|         |    126  | 
|         |    127 // Once upon a time, in a complete fictional  | 
|         |    128 // country there were Persons... | 
|         |    129  | 
|         |    130  | 
|         |    131 abstract class Person | 
|         |    132 case object King extends Person | 
|         |    133 case class Peer(deg: String, terr: String, succ: Int) extends Person | 
|         |    134 case class Knight(name: String) extends Person | 
|         |    135 case class Peasant(name: String) extends Person | 
|         |    136  | 
|         |    137  | 
|         |    138 def title(p: Person): String = p match { | 
|         |    139   case King => "His Majesty the King" | 
|         |    140   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
|         |    141   case Knight(name) => s"Sir ${name}" | 
|         |    142   case Peasant(name) => name | 
|         |    143 } | 
|         |    144  | 
|         |    145 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
|         |    146   case (King, _) => true | 
|         |    147   case (Peer(_,_,_), Knight(_)) => true | 
|         |    148   case (Peer(_,_,_), Peasant(_)) => true | 
|         |    149   case (Peer(_,_,_), Clown) => true | 
|         |    150   case (Knight(_), Peasant(_)) => true | 
|         |    151   case (Knight(_), Clown) => true | 
|         |    152   case (Clown, Peasant(_)) => true | 
|         |    153   case _ => false | 
|         |    154 } | 
|         |    155  | 
|         |    156 val people = List(Knight("David"),  | 
|         |    157                   Peer("Duke", "Norfolk", 84),  | 
|         |    158                   Peasant("Christian"),  | 
|         |    159                   King,  | 
|         |    160                   Clown) | 
|         |    161  | 
|         |    162 println(people.sortWith(superior).mkString("\n")) | 
|         |    163  | 
|         |    164  | 
|         |    165 // String interpolations as patterns | 
|         |    166  | 
|         |    167 val date = "2000-01-01" | 
|         |    168 val s"$year-$month-$day" = date | 
|         |    169  | 
|         |    170 def parse_date(date: String) = date match { | 
|         |    171   case s"$year-$month-$day" => Some((year.toInt, month.toInt, day.toInt)) | 
|         |    172   case s"$day/$month/$year" => Some((year.toInt, month.toInt, day.toInt)) | 
|         |    173   case _ => None | 
|         |    174 }  | 
|         |    175  | 
|         |    176  | 
|         |    177  | 
|     53  |    178  | 
|     54 // User-defined Datatypes and Pattern Matching |    179 // User-defined Datatypes and Pattern Matching | 
|     55 //============================================= |    180 //============================================= | 
|         |    181  | 
|         |    182  | 
|     56  |    183  | 
|     57 abstract class Exp |    184 abstract class Exp | 
|     58 case class N(n: Int) extends Exp                  // for numbers |    185 case class N(n: Int) extends Exp                  // for numbers | 
|     59 case class Plus(e1: Exp, e2: Exp) extends Exp |    186 case class Plus(e1: Exp, e2: Exp) extends Exp | 
|     60 case class Times(e1: Exp, e2: Exp) extends Exp |    187 case class Times(e1: Exp, e2: Exp) extends Exp | 
|    320 jumps(List(1,3,6,1,0,9)).minBy(_.length) |    447 jumps(List(1,3,6,1,0,9)).minBy(_.length) | 
|    321 jumps(List(2,3,1,1,2,4,2,0,1,1)).minBy(_.length) |    448 jumps(List(2,3,1,1,2,4,2,0,1,1)).minBy(_.length) | 
|    322  |    449  | 
|    323  |    450  | 
|    324  |    451  | 
|    325  |    452 // Tail Recursion | 
|         |    453 //================ | 
|         |    454  | 
|         |    455  | 
|         |    456 def fact(n: Long): Long =  | 
|         |    457   if (n == 0) 1 else n * fact(n - 1) | 
|         |    458  | 
|         |    459 fact(10)              //ok | 
|         |    460 fact(10000)           // produces a stackoverflow | 
|         |    461  | 
|         |    462 def factT(n: BigInt, acc: BigInt): BigInt = | 
|         |    463   if (n == 0) acc else factT(n - 1, n * acc) | 
|         |    464  | 
|         |    465 factT(10, 1) | 
|         |    466 factT(100000, 1) | 
|         |    467  | 
|         |    468 // there is a flag for ensuring a function is tail recursive | 
|         |    469 import scala.annotation.tailrec | 
|         |    470  | 
|         |    471 @tailrec | 
|         |    472 def factT(n: BigInt, acc: BigInt): BigInt = | 
|         |    473   if (n == 0) acc else factT(n - 1, n * acc) | 
|         |    474  | 
|         |    475  | 
|         |    476  | 
|         |    477 // for tail-recursive functions the Scala compiler | 
|         |    478 // generates loop-like code, which does not need | 
|         |    479 // to allocate stack-space in each recursive | 
|         |    480 // call; Scala can do this only for tail-recursive | 
|         |    481 // functions | 
|    326  |    482  | 
|    327  |    483  | 
|    328  |    484  | 
|    329  |    485  | 
|    330  |    486  |