changeset 70:4198fa4e0df4

Add Scala code and notes
author IBBoard <dev@ibboard.co.uk>
date Sat, 14 Oct 2017 13:39:41 +0100
parents 05871e7ac124
children 32f018861e36
files .hgignore 4-Scala/README.txt 4-Scala/min.scala 4-Scala/sizer/build.sbt 4-Scala/sizer/project/build.properties 4-Scala/sizer/src/main/scala/example/sizer.scala
diffstat 6 files changed, 104 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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 <movie>{movieName}</movie>" 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 <code>" 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
--- /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
--- /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"
--- /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
--- /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