updated
authorChristian Urban <urbanc@in.tum.de>
Sat, 04 Nov 2017 16:17:19 +0000
changeset 124 c45d3cd9a749
parent 123 556cd74cbba9
child 125 dcaab8068baa
updated
handouts/pep-ho.pdf
handouts/pep-ho.tex
progs/lecture1.scala
progs/mandelbrot.scala
Binary file handouts/pep-ho.pdf has changed
--- a/handouts/pep-ho.tex	Thu Nov 02 14:47:55 2017 +0000
+++ b/handouts/pep-ho.tex	Sat Nov 04 16:17:19 2017 +0000
@@ -38,9 +38,10 @@
 res0: Int = 5
 \end{lstlisting}
 
-\noindent indicating that the result of the addition is of
-type \code{Int} and the actual result is 5. Another classic
-example you can try out is
+\noindent indicating that the result of the addition is of type
+\code{Int} and the actual result is 5; \code{res0} is a name that
+Scala gives automatically to the result. Yoy can reuse this name later
+on. Another classic example you can try out is
 
 \begin{lstlisting}[numbers=none]
 scala> print("hello world")
@@ -49,7 +50,7 @@
 
 \noindent Note that in this case there is no result. The
 reason is that \code{print} does not actually produce a result
-(there is no \code{resXX} and no type), rather it is a
+(there is no \code{resX} and no type), rather it is a
 function that causes the \emph{side-effect} of printing out a
 string. Once you are more familiar with the functional
 programming-style, you will know what the difference is
@@ -57,7 +58,7 @@
 function that causes a side-effect, like \code{print}. We
 shall come back to this point later, but if you are curious
 now, the latter kind of functions always has \code{Unit} as
-return type.
+return type. It is just not printed.
 
 You can try more examples with the Scala interpreter, but try
 first to guess what the result is (not all answers by Scala are obvious):
@@ -75,7 +76,7 @@
 scala> "12345".length
 \end{lstlisting}
 
-\subsection*{Stand-Alone Apps}
+\subsection*{Stand-Alone Scala Apps}
 
 If you want to write a stand-alone app in Scala, you can
 implement an object that is an instance of \code{App}, say
@@ -86,7 +87,7 @@
 }
 \end{lstlisting}
 
-\noindent save it in a file, say {\tt hello-world.scala}, and
+\noindent save it in a file, for example {\tt hello-world.scala}, and
 then run the compiler and runtime environment:
 
 \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small]
@@ -95,6 +96,7 @@
 hello world
 \end{lstlisting}
 
+\noindent
 Like Java, Scala targets the JVM and consequently
 Scala programs can also be executed by the bog-standard Java
 Runtime. This only requires the inclusion of {\tt
@@ -112,10 +114,10 @@
 
 \subsection*{Values}
 
-In the lectures, I will try as much as possible to avoid the term
-\emph{variables} familiar from other programming languages. Scala
-has \emph{values}, which can be seen as abbreviations of larger
-expressions. For example
+In the lectures I will try to avoid as much as possible the term
+\emph{variables} familiar from other programming languages. The reason
+is that Scala has \emph{values}, which can be seen as abbreviations of
+larger expressions. For example
 
 \begin{lstlisting}[numbers=none]
 scala> val x = 42
@@ -130,8 +132,8 @@
 
 \noindent
 Why the kerfuffle about values? Well, values are \emph{immutable}. You cannot
-change their value after you defined them. If you try to reassign, say,
-\code{z}, Scala will yell at you:
+change their value after you defined them. If you try to reassign
+\code{z} above, Scala will yell at you:
 
 \begin{lstlisting}[numbers=none]
 scala> z = 9
@@ -151,7 +153,7 @@
 scala> println(z) 
 \end{lstlisting}
 
-\noindent but try to guess what Scala will print out in the code above
+\noindent but try to guess what Scala will print out 
 for \code{z}?  Will it be \code{6} or \code{10}? A final word about
 values: Try to stick to the convention that names of values should be
 lower case, like \code{x}, \code{y}, \code{foo41} and so on.
@@ -159,7 +161,8 @@
 
 \subsection*{Function Definitions}
 
-A function \code{f} taking a single argument of type \code{Int} can be defined
+We do functional programming. So defining functions will be our main occupation.
+A function \code{f} taking a single argument of type \code{Int} can be defined in Scala
 as follows:
 
 \begin{lstlisting}[numbers=none]
@@ -167,9 +170,10 @@
 \end{lstlisting} 
 
 \noindent
-It returns the value resulting from evaluating the expression
+This function returns the value resulting from evaluating the expression
 \code{EXPR} (whatever is substituted for this). The result will be
-of type \code{String}. Simple examples of Scala functions are:
+of type \code{String}. It is a good habbit to include this information
+about the return type always. Simple examples of Scala functions are:
 
 \begin{lstlisting}[numbers=none]
 def incr(x: Int) : Int = x + 1
@@ -188,10 +192,11 @@
 
 \noindent
 where each argument requires its type and the result type of the
-function, \code{rty}, shoudl be given. If the body of the  function
-is more complex, then it can be enclosed in braces; it it is just a
-simple expression, like \code{x + 1}, you can omit the braces. Very
-often functions are recursive (call themselves) like
+function, \code{rty}, should be given. If the body of the function is
+more complex, then it can be enclosed in braces, like above. If it it
+is just a simple expression, like \code{x + 1}, you can omit the
+braces. Very often functions are recursive (call themselves) like
+the venerable factorial function.
 
 \begin{lstlisting}[numbers=none]
 def fact(n: Int): Int = 
--- a/progs/lecture1.scala	Thu Nov 02 14:47:55 2017 +0000
+++ b/progs/lecture1.scala	Sat Nov 04 16:17:19 2017 +0000
@@ -226,7 +226,7 @@
 gcd_db(48, 18)
 
 
-// Assert/Testing
+// Asserts/Testing
 //================
 
 assert(gcd(48, 18) == 6)
@@ -302,7 +302,7 @@
 
 
 // function for looking up stockmarket data 
-def price_lookup(symbol: String): String = {
+def price_lookup(symbol: String) : String = {
   val url = "https://download.finance.yahoo.com/d/quotes.csv?s=" + symbol + "&f=snl1"
   Source.fromURL(url).mkString.drop(1).dropRight(2)
 }
@@ -373,11 +373,12 @@
 // run Scala on the commandline. There are also at least 
 // four IDEs you can use with Scala:
 //
-//  (0) Some general information for setting up IDEs
+//  (0) Some general information about setting up IDEs
 //	    with Scala support can be found at
 //
 //         http://docs.scala-lang.org/getting-started.html 
 //
+//
 //  (1) Eclipse for Scala (one big bundle)
 //
 //         http://scala-ide.org/download/sdk.html
@@ -388,7 +389,7 @@
 //		   http://docs.scala-lang.org/getting-started-intellij-track/getting-started-with-scala-in-intellij.html	  
 //
 //  (3) Sublime (not free, but unlimited trial period; 
-//	    needs SublimeREPL plugin)
+//	    needs Scala and SublimeREPL plugin)
 //
 //         https://www.sublimetext.com
 //
@@ -406,6 +407,13 @@
 //   
 // There is also Scala support in the Atom editor, but my
 // experience is mixed. People also use Scala with Vim and Jedit.
+// Finally there is an online editor specifically designed for 
+// running Scala applications (but do not blame mne if you lose all 
+// what you typed in):
+//
+//      https://scalafiddle.io 
+//
+//
 //
 // All of the IDEs above support a REPL for Scala. Some of them have
 // the very nifty feature of a Scala Worksheet -- you just save your
@@ -415,6 +423,7 @@
 //
 //
 // Scala Library Docs
+//====================
 //
 //  http://www.scala-lang.org/api/current/
 //
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/mandelbrot.scala	Sat Nov 04 16:17:19 2017 +0000
@@ -0,0 +1,133 @@
+import java.awt.Color
+import java.awt.Dimension
+import java.awt.Graphics
+import java.awt.Graphics2D
+import java.awt.image.BufferedImage
+import javax.swing.JFrame
+import javax.swing.JPanel
+import javax.swing.WindowConstants
+
+// complex numbers
+case class Complex(val a: Double, val b: Double) { 
+    // represents the complex number a + b*i
+    def +(that: Complex) = Complex(this.a + that.a, this.b + that.b)
+    def -(that: Complex) = Complex(this.a - that.a, this.b - that.b)
+    def *(that: Complex) = Complex(this.a * that.a - this.b * that.b,
+                                   this.a * that.b + that.a * this.b)
+    def *(that: Double) = Complex(this.a * that, this.b * that)
+    def abs() = Math.sqrt(this.a * this.a + this.b * this.b)
+}
+
+// some customn colours
+val colours = List(
+    new Color(66, 30, 15),    new Color(25, 7, 26),
+    new Color(9, 1, 47),      new Color(4, 4, 73),
+    new Color(0, 7, 100),     new Color(12, 44, 138),
+    new Color(24, 82, 177),   new Color(57, 125, 209),
+    new Color(134, 181, 229), new Color(211, 236, 248),
+    new Color(241, 233, 191), new Color(248, 201, 95),
+    new Color(255, 170, 0),   new Color(204, 128, 0),
+    new Color(153, 87, 0),    new Color(106, 52, 3))
+
+// the viewer panel
+class Viewer(width: Int, height: Int) extends JPanel {
+    val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
+    clearCanvas(Color.black)
+
+    override def paintComponent(g: Graphics) = 
+      g.asInstanceOf[Graphics2D].drawImage(canvas, null, null)
+
+    override def getPreferredSize() = 
+       new Dimension(width, height)
+
+    def clearCanvas(color: Color) = {
+      for(x <- 0 to width - 1;
+          y <- 0 to height - 1) canvas.setRGB(x, y, color.getRGB())
+      repaint()
+    }  
+
+}
+
+def openViewer(width: Int, height: Int) = {
+    val frame = new JFrame("XYPlane")
+    val viewer = new Viewer(width, height)
+    frame.add(viewer)
+    frame.pack()
+    frame.setVisible(true)
+    frame.setResizable(false)
+    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
+    viewer
+}
+
+val W = 900
+val H = 800 
+val black = Color.black
+val viewer = openViewer(W, H)
+
+
+def pixel(x: Int, y: Int, color: Color) = 
+  viewer.canvas.setRGB(x, y, color.getRGB())
+  
+
+def mandelbrot(start: Complex, end: Complex, level: Int) : Unit = {
+  viewer.clearCanvas(black)
+   
+  val delta_x = (end.a - start.a) / W
+  val delta_y = (end.b - start.b) / H
+   
+  for (y0 <- (0 until H).par) {
+    for (x0 <- (0 until W).par) {
+    
+     val c = start + Complex(x0 * delta_x, y0 * delta_y)
+
+     def iters(z: Complex, it: Int) : Color = {
+       if (it < level && z.abs < 2) iters(z * z + c, it + 1) else 
+        if (it == level) black else colours(it % 16) 
+     }
+
+     pixel(x0, y0, iters(Complex(0, 0), 0))
+   }
+   viewer.updateUI()
+ }
+}
+
+// Examples
+//==========
+
+//for measuring time
+def time_needed[T](code: => T) = {
+  val start = System.nanoTime()
+  code
+  val end = System.nanoTime()
+  (end - start) / 1.0e9
+}
+
+
+// example 1
+val exa1 = Complex(-2.0, -1.5)
+val exa2 = Complex( 1.0,  1.5)
+
+time_needed(mandelbrot(exa1, exa2, 1000))
+
+// ehxample 2
+val exb1 = Compylex(-0.37465401, 0.659227668)
+val exb2 = Complex(-0.37332410, 0.66020767)
+
+time_needed(mandelbrot(exb1, exb2, 1000))
+
+// example 3
+val exc1 = Complex(0.435396403, 0.367981352)
+val exc2 = Complex(0.451687191, 0.380210061)
+
+time_needed(mandelbrot(exc1, exc2, 1000))
+
+// some more computations with example 3
+val delta = (exc2 - exc1) * 0.0333
+
+time_needed(
+for (i <- (0 to 12)) 
+  mandelbrot(exc1 + delta * i, 
+             exc2 - delta * i, 1000))
+
+
+