# HG changeset patch # User IBBoard # Date 1507984781 -3600 # Node ID 4198fa4e0df410745231929e411e1dacfa985ec7 # Parent 05871e7ac124ac773f810ce3bbc0884b8b40597b Add Scala code and notes diff -r 05871e7ac124 -r 4198fa4e0df4 .hgignore --- a/.hgignore Sat Oct 07 16:50:14 2017 +0100 +++ b/.hgignore Sat Oct 14 13:39:41 2017 +0100 @@ -1,1 +1,2 @@ -2-Io/matrix.txt \ No newline at end of file +2-Io/matrix.txt +target/ \ No newline at end of file diff -r 05871e7ac124 -r 4198fa4e0df4 4-Scala/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4-Scala/README.txt Sat Oct 14 13:39:41 2017 +0100 @@ -0,0 +1,28 @@ +I've already done Scala development at work, so most of this is just a recap. + +A few things I learned: + + * Never used traits before - mini classes defined with "trait" keyword and included + like a "mixin" with the "with" keyword to 'inherit' functionality from multiple parents + * Nil is an empty list - probably useful when iterating things and returning a Nil + * foldLeft either uses strange syntax ("start /: list {(a, b) … }") or uses currying + ("list.foldLeft(start)((a,b) …)") + * Strings can be converted to regexes by adding ".r" at the end (I think my work code + managed to do without string matching) + * Pattern matching with a "match… case" on XML can use squiggly brackets to name a variable + (e.g. "case {movieName}" matches the tag and puts the contents in movieName) + * Scala has a few minor problems: + * 2.12 (RPM from the website) won't run files as "scala filename.scala" - it needs to be + "scala -nc filename.scala" to disable the compilation daemon + * "scala -e " doesn't seem to want to work without "-nc" either + * If there are dependencies then it is easier to use sbt. Download from + http://www.scala-sbt.org/download.html, create a standard "project/src/scala/package" + structure then create build.sbt within "project/" with the contents: + name := "Project-Name" + version := "1.0" + scalaVersion := "2.12.3" + Run the project by cd-ing into the project directory and running "sbt run" + * Actors have been deprecated and replaced by Akka + * sbt compiles code, so you can't have code outside a class or object + * Akka actors can only act - they can't easily have other methods as well because + creation returns a generic Akka reference to the actor, which doesn't expose the method \ No newline at end of file diff -r 05871e7ac124 -r 4198fa4e0df4 4-Scala/min.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4-Scala/min.scala Sat Oct 14 13:39:41 2017 +0100 @@ -0,0 +1,1 @@ +println("Hello, world!") \ No newline at end of file diff -r 05871e7ac124 -r 4198fa4e0df4 4-Scala/sizer/build.sbt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4-Scala/sizer/build.sbt Sat Oct 14 13:39:41 2017 +0100 @@ -0,0 +1,8 @@ +name := "Sizer" + +version := "1.0" + +scalaVersion := "2.12.3" + +// https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor_2.12 +libraryDependencies += "com.typesafe.akka" % "akka-actor_2.12" % "2.5.6" diff -r 05871e7ac124 -r 4198fa4e0df4 4-Scala/sizer/project/build.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4-Scala/sizer/project/build.properties Sat Oct 14 13:39:41 2017 +0100 @@ -0,0 +1,1 @@ +sbt.version=1.0.2 diff -r 05871e7ac124 -r 4198fa4e0df4 4-Scala/sizer/src/main/scala/example/sizer.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4-Scala/sizer/src/main/scala/example/sizer.scala Sat Oct 14 13:39:41 2017 +0100 @@ -0,0 +1,64 @@ +package example + +import scala.io._ +import akka.actor.{Actor,ActorSystem,Props} + +object PageLoader { + def getPageSize(url : String) : Int = { + try { + return Source.fromURL(url).mkString.length + } catch { + case e:Exception => + return -1 + } + } +} + +class ConcurrentActor extends Actor { + def receive = { + case (url, size) => println("Size for " + url + ": " + size) + } +} + +object Main { + val urls = List( + "https://www.amazon.com/", + "https://twitter.com/", + "https://www.google.co.uk/", + "https://www.bbc.co.uk/news/" + ) + + val system = ActorSystem("MySystem") + val actor = system.actorOf(Props[ConcurrentActor], name="concurrent-actor") + + def timeMethod(method: () => Unit) = { + val start = System.nanoTime + method() + val end = System.nanoTime + println("+++ Method took " + (end - start) / 1000000000.0 + " seconds.") + } + + def getPageSizeSequentially() = { + for (url <- urls) { + println("Size for " + url +": " + PageLoader.getPageSize(url)) + } + } + + def getPageSizeConcurrently() = { + for (url <- urls) { + // Send a message to the actor (which won't arrive until the PageLoader call completes) + println(s"Sending message for $url") + actor ! (url, PageLoader.getPageSize(url)) + } + } + + def main(args: Array[String]) { + println("Sequential:") + timeMethod { getPageSizeSequentially } + + println("Concurrent:") + timeMethod { getPageSizeConcurrently } + system.stop(actor) + system.terminate() + } +} \ No newline at end of file