# HG changeset patch # User Christian Urban # Date 1720963899 -3600 # Node ID 4ffba2f726929440f85cb573d51c6aa59f024420 # Parent e2ffe8642f552cbb358ea8e2ae3615a22653e991 updated diff -r e2ffe8642f55 -r 4ffba2f72692 cws/resit2.tex --- a/cws/resit2.tex Thu Jun 13 13:13:33 2024 +0100 +++ b/cws/resit2.tex Sun Jul 14 14:31:39 2024 +0100 @@ -52,7 +52,7 @@ \noindent You are asked to implement a Scala program for playing the Shogun -board game. The deadline for your submission is on XXX at +board game. The deadline for your submission is on 26th July at 16:00. Make sure you use \texttt{scala-cli} and Scala version \textbf{3.XX} for the resit---the same version as during the lectures. \medskip diff -r e2ffe8642f55 -r 4ffba2f72692 handouts/pep-ho.pdf Binary file handouts/pep-ho.pdf has changed diff -r e2ffe8642f55 -r 4ffba2f72692 handouts/pep-ho.tex --- a/handouts/pep-ho.tex Thu Jun 13 13:13:33 2024 +0100 +++ b/handouts/pep-ho.tex Sun Jul 14 14:31:39 2024 +0100 @@ -72,7 +72,7 @@ % % We can achieve the same results using .map(): % -% const prices = [19.99, 4.95, 25, 3.50]; +% const prices = [19.99, 4.95, 25, 3.50]; % let new_prices = prices.map(price => price * 1.06); % % The syntax above is condensed so let’s walk through it a bit. The @@ -82,7 +82,7 @@ % input, we can omit the usual parentheses around the parameters. % potentially a worked example? Tetris in scala.js -% +% % https://medium.com/@michael.karen/learning-modern-javascript-with-tetris-92d532bcd057 % % Scala videos @@ -90,7 +90,7 @@ %% https://alvinalexander.com/downloads/HelloScala-FreePreview.pdf -%% +%% %% Section 10 about strings; interpolations and multiline strings % Easy installation @@ -122,7 +122,7 @@ \definecolor{cellbackground}{HTML}{F7F7F7} - + \begin{document} \fnote{\copyright{} Christian Urban, King's College London, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024} @@ -132,12 +132,12 @@ \section*{A Crash-Course in Scala} -\mbox{}\hfill\textit{``Scala --- \underline{S}lowly \underline{c}ompiled +\mbox{}\hfill\textit{``Scala --- \underline{S}lowly \underline{c}ompiled \underline{a}cademic \underline{la}nguage''}\smallskip\\ \mbox{}\hfill\textit{ --- a joke(?) found on Twitter}\bigskip \mbox{}\hfill\textit{``Life is too short for \texttt{malloc}.''}\smallskip\\ -\mbox{}\hfill\textit{ --- said Neal Ford at Oscon'13}\;\hr{https://www.youtube.com/watch?v=7aYS9PcAITQ}\bigskip\\ +\mbox{}\hfill\textit{ --- said Neal Ford at Oscon'13}\;\hr{https://www.youtube.com/watch?v=7aYS9PcAITQ}\bigskip\\ % In 1982, James or Jim Morris wrote: % @@ -164,10 +164,10 @@ programmers to write very concise and elegant code. Some therefore say ``Scala is the better Java''.\footnote{from \url{https://www.slideshare.net/maximnovak/joy-of-scala}, though this might -be outdated as latest versions of Java are catching up somewhat} +be outdated as latest versions of Java are catching up somewhat} A number of companies---the Guardian, Duolingo, Coursera, FourSquare, -Netflix, LinkedIn, ITV to name a few---either use Scala exclusively in +Netflix, LinkedIn, ITV, Disney to name a few---either use Scala exclusively in production code, or at least to some substantial degree. Scala seems also useful in job-interviews (especially in data science) according to this anecdotal report @@ -194,16 +194,16 @@ \begin{tcolorbox}[colback=red!5!white,colframe=red!75!black] I will be using the \textbf{\texttt{scala-cli}} REPL for Scala 3, rather than the ``plain'' Scala REPL. This is a batteries included version of - Scala 3 and is easier to use and install. In fact + Scala 3 and is easier to use and to install. In fact \texttt{scala-cli} is designated to replace the ``plain'' Scala REPL in future versions of Scala. So why not using it now? It can be downloaded from: \begin{center} - \url{https://scala-cli.virtuslab.org} - \end{center} -\end{tcolorbox}\medskip + \url{https://scala-cli.virtuslab.org} + \end{center} +\end{tcolorbox}\medskip \noindent @@ -242,11 +242,11 @@ Figure~\ref{vscode} for my setup). \begin{figure}[t] -\begin{boxedminipage}{\textwidth} -\begin{center} +\begin{boxedminipage}{\textwidth} +\begin{center} \includegraphics[scale=0.15]{../pics/vscode.png}\\[-10mm]\mbox{} \end{center} -\caption{My installation of VS Code / Codium includes the +\caption{My installation of VS Code / Codium includes the package \textbf{Scala Syntax (official)} 0.5.7 from Marketplace. I have also bound the keys \keys{Ctrl} \keys{Ret} to the action ``Run-Selected-Text-In-Active-Terminal'' in order to quickly @@ -254,10 +254,10 @@ terminal to run \texttt{scala-cli} version 1.0.5 which uses Scala 3.3.1.\label{vscode}} \end{boxedminipage} -\end{figure} +\end{figure} Actually \alert last year I switched to VS Codium as IDE for writing Scala programs. VS Codium is VS Code -minus all the telemetry that is normally sent to Microsoft. Apart from +minus all the telemetry data that is normally sent to Microsoft. Apart from the telemetry (and Copilot, which you are not supposed to use anyway), it works pretty much the same way as the original but is driven by a dedicated community, rather than a big company. You can download VS @@ -276,15 +276,15 @@ for developing and running Scala programs: for example \textit{Scastie} is one of them. It requires zero setup (assuming you have a browser handy). You can access it at - + \begin{quote} \url{https://scastie.scala-lang.org} \end{quote} - + \noindent But you should be careful if you use them for your coursework: they -are meant to play around, not really for serious work. Make -sure your \texttt{scala-cli} works on your own machine ASAP! +are meant to play around, not really for serious work. Therefore make +sure \texttt{scala-cli} works on your own machine ASAP! As one might expect, Scala can be used with the heavy-duty IDEs Eclipse and IntelliJ. For example IntelliJ includes plugins for @@ -296,9 +296,9 @@ \noindent \underline{\textbf{BUT}}, I do \textbf{not} recommend the usage of -either Eclipse or IntelliJ for PEP: these IDEs seem to make your life -harder, rather than easier, for the small programs that we will write -in this module. They are really meant to be used when you have a +either Eclipse or IntelliJ for PEP: for the small programs that we will write +in this module, these IDEs seem to make your life +harder, rather than easier. They are really meant to be used when you have a million-lines codebase instead of our small ``toy-programs''\ldots{}for example why on earth am I required to create a completely new project with several subdirectories when I @@ -337,7 +337,7 @@ programming is a \texttt{for}-loop in say Java and C/C++. Consider the snippet: \begin{lstlisting}[language=C,numbers=none] -for (int i = 10; i < 20; i++) { +for (int i = 10; i < 20; i++) { //...do something with i... } \end{lstlisting} @@ -355,7 +355,7 @@ \begin{center} \includegraphics[scale=0.25]{../pics/root-of-all-evil.png} -\end{center} +\end{center} \noindent @@ -376,8 +376,9 @@ advantage of these cores by running as much of your code as possible in parallel on as many cores you have available (typically 4-8 or even more in modern laptops and sometimes much more on high-end -machines---and we conveniently ignore how many cores are on modern -GPUs). In this situation \textit{mutable} variables like \texttt{i} in +machines---and we conveniently ignore here how many cores are on modern +GPUs, which can be hundreds or even thousands). In this situation +\textit{mutable} variables like \texttt{i} in the for-loop above are evil, or at least a major nuisance: Because if you want to distribute some of the loop-iterations over several cores that are currently idle in your system, you need to be extremely @@ -388,7 +389,7 @@ Especially the writing operation is critical because you do not want that conflicting writes mess about with \texttt{i}. Take my word: an untold amount of misery has arisen from this problem. The catch is -that if you try to solve this problem in C/C++ or Java, and be as +that if you try to solve this problem in languages like C/C++ or Java, and be as defensive as possible about reads and writes to \texttt{i}, then you need to synchronise access to it. The result is that very often your program waits more than it runs, thereby defeating the point of trying @@ -397,14 +398,16 @@ random results. And forget the idea of being able to debug such code. If you want to watch a 5-minute video of horror stories, feel free to follow \ldots{} -\hr{https://www.youtube.com/watch?v=LdLUgCJkiHY} (I love the fact, he -says at 4:02 that he does not understand how the JVM really +\hr{https://www.youtube.com/watch?v=LdLUgCJkiHY} \raisebox{-0.7mm}{\emoji{rofl}} (I love the fact, he +says at 4:02 mins that he does not understand how the JVM really works\ldots{} I always assumed I am the only idiot who does not -understand how threads work on the JVM. Apparently not. \raisebox{-0.7mm}{\emoji{rofl}})\bigskip +understand how threads work on the JVM. Apparently not. +But the point is that I am a functional programmer: I do not care -- I do not have to +understand them.)\bigskip \noindent The central idea of functional programming is to eliminate any state -and mutable variables from programs---or at least from the ``interesting bits'' of the +and all mutable variables from programs---or at least from the ``interesting bits'' of the programs. Because then it is easy to parallelise the resulting programs: if you do not have any state, then once created, all memory content stays unchanged and reads to such memory are absolutely safe @@ -422,11 +425,11 @@ \begin{figure}[p] \begin{boxedminipage}{\textwidth} -A Scala program for generating pretty pictures of the Mandelbrot set.\smallskip\\ +A Scala program for generating pretty pictures of the Mandelbrot set.\smallskip\\ (See \url{https://en.wikipedia.org/wiki/Mandelbrot_set} or\\ \phantom{(See }\url{https://www.youtube.com/watch?v=aSg2Db3jF_4}): -\begin{center} -\begin{tabular}{c} +\begin{center} +\begin{tabular}{c} \includegraphics[scale=0.11]{../pics/mand1.png}\\[-8mm]\mbox{} \end{tabular} \end{center} @@ -441,35 +444,35 @@ {\footnotesize\begin{lstlisting}[xleftmargin=-1mm] for (y <- (0 until H)) { for (x <- (0 until W)) { - - val c = start + + + val c = start + (x * d_x + y * d_y * i) - val iters = iterations(c, max) - val colour = - if (iters == max) black + val iters = iterations(c, max) + val colour = + if (iters == max) black else colours(iters % 16) pixel(x, y, colour) } viewer.updateUI() -} -\end{lstlisting}} -& +} +\end{lstlisting}} +& {\footnotesize\begin{lstlisting}[xleftmargin=0mm] for (y <- (0 until H).par) { for (x <- (0 until W).par) { - - val c = start + + + val c = start + (x * d_x + y * d_y * i) - val iters = iterations(c, max) - val colour = - if (iters == max) black + val iters = iterations(c, max) + val colour = + if (iters == max) black else colours(iters % 16) - + pixel(x, y, colour) } viewer.updateUI() -} +} \end{lstlisting}}\\[-2mm] \centering\includegraphics[scale=0.5]{../pics/cpu2.png} & @@ -481,21 +484,21 @@ ``ranges'' of the x and y coordinates. As can be seen from the CPU loads, in the sequential version there is a lower peak for an extended period, while in the parallel version there is a short sharp burst for -essentially the same workload\ldots{}meaning you get more work done -in a shorter amount of time. This easy \emph{parallelisation} +essentially the same workload\ldots{}meaning you get more work done +in a shorter amount of time. This easy \emph{parallelisation} only works reliably with immutable programs. -\label{mand}} +\label{mand}} \end{boxedminipage} -\end{figure} +\end{figure} But remember this easy parallelisation of code requires that we have no -state in our programs\ldots{}that is no counters like \texttt{i} in +state in our programs\ldots{}that is \emph{no} counters like \texttt{i} in \texttt{for}-loops. You might then ask, how do I write loops without such counters? Well, teaching you that this is possible is one of the -main points of the Scala-part in PEP. I can assure you it is possible, +main points of the Scala-part in PEP. I can assure you it \emph{is} possible, but you have to get your head around it. Once you have mastered this, it will be fun to have no state in your programs (a side product is that it -much easier to debug state-less code and also more often than not easier +much easier to debug state-less code and it is also more often than not easier to understand). So have fun with Scala!\footnote{If you are still not convinced about the function programming ``thing'', there are a few more arguments: a lot of research in programming languages happens to take @@ -526,6 +529,9 @@ \url{https://archive.ph/vrofC} \end{quote} +\noindent +Relevant xkcd entries about functional programming are XXX. + \subsection*{The Very Basics} Let us get back to Scala and \texttt{scala-cli}: One advantage of @@ -560,7 +566,7 @@ \end{lstlisting} \noindent The answer means that he result of the addition is of type -0\code{Int} and the actual result is 5; \code{res0} is a name that +\code{Int} and the actual result is 5; \code{res0} is a name that Scala gives automatically to the result. You can reuse this name later on, for example @@ -577,7 +583,7 @@ hello world \end{lstlisting} -\noindent Note that in this case there is no result. The +\noindent Note that in this case there is no result! The reason is that \code{println} does not actually produce a result (there is no \code{resX} and no type), rather it is a function that causes the \emph{side-effect} of printing out a @@ -587,7 +593,7 @@ function that causes a side-effect, like \code{println}. 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. It is just not printed by Scala. +return type. It is just not printed by Scala. You can try more examples with the \texttt{scala-cli} REPL, but feel free to first guess what the result is (not all answers by Scala are obvious): @@ -608,11 +614,14 @@ scala> List(1) == List(1) scala> Array(1) == Array(1) scala> Array(1).sameElements(Array(1)) +scala> 0.1 + 0.2 == 0.3 \end{lstlisting} \noindent -Also observe carefully what Scala responds in the following -three instances involving the constant \lstinline!1!---can +If you think Scala's answer in the last line is braindamaged, try the +same in your own favourite language. +Also observe carefully what Scala responds in the following +three instances involving the constant \lstinline!1!---can you explain the differences? @@ -636,7 +645,7 @@ \texttt{@main}. For example write \begin{lstlisting}[numbers=none] -@main +@main def Hello() = println("hello world") \end{lstlisting} @@ -645,11 +654,11 @@ %} \noindent save it in a file, say {\tt hello-world.scala}, and -then use \texttt{scala-cli run} (which internally compiles the +then use \texttt{scala-cli} (which compiles the scala file and runs it): \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] -$ scala-cli run hello-world.scala +$ scala-cli hello-world.scala hello world \end{lstlisting} @@ -669,8 +678,8 @@ \begin{tcolorbox}[colback=red!5!white,colframe=red!75!black] Do not use \code{var} in your code for PEP! This declares a mutable variable. - Only use \code{val}! -\end{tcolorbox}\medskip + Only use \code{val}! This is for \emph{immutable} values. +\end{tcolorbox}\medskip \noindent In the lectures I will try to avoid as much as possible the term @@ -691,7 +700,7 @@ \end{lstlisting} \noindent -As can be seen, we first define \code{x} and {y} with admittedly some silly +As can be seen, we first define \code{x} and \code{y} with admittedly some silly expressions, and then reuse these values in the definition of \code{z}. All easy, right? Why the kerfuffle about values? Well, values are \emph{immutable}. You cannot change their value after you defined them. @@ -715,33 +724,33 @@ scala> val x = 42 scala> val z = x / 7 scala> val x = 70 -scala> println(z) +scala> println(z) \end{lstlisting} -\noindent but try to guess what Scala will print out +\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. Upper-case -names you should reserve for what is called \emph{constructors}. And +names you should reserve for what is called \emph{constructors}. And forgive me when I call values as variables\ldots{}it is just something that -has been in imprinted into my developer-DNA during my early days and -is difficult to get rid of.~\texttt{;o)} +has been in imprinted into my developer-DNA during my early years and +is difficult to get rid of.~\texttt{;o)} \subsection*{Function Definitions} We do functional programming! So defining functions will be our main occupation. -As an example, a function named \code{f} taking a single argument of type +As an example, a function named \code{f} taking a single argument of type \code{Int} can be defined in Scala as follows: \begin{lstlisting}[numbers=none] -def f(x: Int) : String = ...EXPR... -\end{lstlisting} +def f(x: Int) : String = ...YOUR CODE... +\end{lstlisting} \noindent This function returns the value resulting from evaluating the expression -\code{EXPR} (whatever is substituted for this). Since we declared -\code{String}, the result of this function will be of type +what your code is. Since we declared +\code{String} after the colon, the result of this function will be of type \code{String}. It is a good habit to always include this information about the return type, while it is only strictly necessary to give this type in recursive functions (later more on that). Simple examples of Scala functions are: @@ -757,12 +766,12 @@ \begin{lstlisting}[numbers=none] def fname(arg1: ty1, arg2: ty2,..., argn: tyn): rty = { - ...BODY... + ...BODY_OF_FUNCTION... } \end{lstlisting} \noindent -where each argument, \texttt{arg1}, \texttt{arg2} and so on, requires +where each argument, \texttt{arg1}, \texttt{arg2} and so on, requires its type and the result type of the function, \code{rty}, should also be given. If the body of the function is more complex, then it can be enclosed in braces, like above. If it @@ -771,19 +780,20 @@ like the venerable factorial function: \begin{lstlisting}[numbers=none] -def fact(n: Int) : Int = +def fact(n: Int) : Int = if (n == 0) 1 else n * fact(n - 1) \end{lstlisting} \noindent -where we have to give the return type \code{Int}. Note we could also +In this case we have to give the return type \code{Int}. But as said, it is a good +habit to give the return type for all functions. Note we could also have written this with braces as \begin{lstlisting}[numbers=none] def fact(n: Int) : Int = { - if (n == 0) 1 + if (n == 0) 1 else n * fact(n - 1) -} +} \end{lstlisting} \noindent @@ -796,28 +806,29 @@ unique in that for nearly 20 years of its existence\ldots{}until Scala 3 came along. While people like me have perfectly adapted to the sight of \code{if}s without \code{then}s, it seems the developers of Scala -caved in to the special eyesight of Gen-Python people and now allow to +caved in to the special eyesight of Gen-Python people (I am sure that is not you) and now allow to write the same function also as \begin{lstlisting}[numbers=none] def fact(n: Int) : Int = { - if n == 0 - then 1 + if n == 0 then 1 else n * fact(n - 1) -} +} \end{lstlisting} \noindent -I accept this might look a bit more familiar to beginners of Scala, if -they come from other languages, like Java or C++. But that we also had +The main difference between both versions is that if you want to drop the \code{then}, then you need to +enclose the boolean expression within parentheses. +I accept the second version might look a bit more familiar to beginners of Scala, if +they come from other languages, like Python, Java or C++. But that we also had to get rid in Scala 3 of the familiar \texttt{\{\}}-parentheses is completely beyond me. So in Scala 3 the braces are optional and the \texttt{fact}-function can even be written as \begin{lstlisting}[numbers=none] -def fact(n: Int) : Int = +def fact(n: Int) : Int = if n == 0 - then 1 + then 1 else n * fact(n - 1) \end{lstlisting} @@ -827,7 +838,7 @@ I will \textbf{not} show you any of my code in the newfangled Pythonesque meaningful-indent-syntax. When necessary, I will always use braces to indicate the beginning and end of a code block, and I -have not yet get completely get used to the \code{if}s with +have not yet completely got used to the \code{if}s with \code{then}s. Please forgive me for being still inconsistent with this\footnote{Scala adopted some very fine features of Python, for example string interpolations, but that we had to completely cave in to the demands of Gen-Python is a bridge too far for my completely insignificant opinion. @@ -859,7 +870,7 @@ val s = xs.sum val n = xs.length s / n -} +} \end{lstlisting} \noindent In this example the expression \code{s / n} is in the last @@ -867,7 +878,7 @@ calculates. The two lines before just calculate intermediate values. This principle of the ``last-line'' comes in handy when you need to print out values, for example, for debugging purposes. Suppose you want -rewrite the function as +rewrite the average function as \begin{lstlisting}[numbers=none] def average(xs: List[Int]) : Int = { @@ -876,7 +887,7 @@ val h = xs.head println(s"Input $xs with first element $h") s / n -} +} \end{lstlisting} \noindent @@ -896,7 +907,7 @@ def average(xs: List[Int]) : Int = { if (xs.length == 0) 0 else xs.sum / xs.length -} +} \end{lstlisting} \noindent @@ -919,11 +930,12 @@ def avr_minmax(xs: List[Int]) : (Int, Int, Int) = { if (xs.length == 0) (0, 0, 0) else (xs.min, xs.sum / xs.length, xs.max) -} +} \end{lstlisting} \noindent -which still satisfies the rule-of-thumb. +which still satisfies the rule-of-thumb: The result of the function is the +last expression that is run inside the function. \begin{tcolorbox}[colback=red!5!white,colframe=red!75!black] Do not use \code{return} in your code to indicate what a function @@ -939,7 +951,7 @@ not really have loops. It has instead, what is in functional programming called, \emph{maps}. To illustrate how they work, let us assume you have a list of numbers from 1 to 8 and want to -build the list of squares. The list of numbers from 1 to 8 +build the list of corresponding squares. The list of numbers from 1 to 8 can be constructed in Scala as follows: \begin{lstlisting}[numbers=none,language={}] @@ -947,12 +959,14 @@ val res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8) \end{lstlisting} -\noindent Generating from this list the list of corresponding -squares in a programming language such as Java, you would assume +\noindent Like in modern versions of Java, the \code{1 to 8} generates a \code{Range}, which is then +transformed into a list by the \code{.toList}. +Generating from this list the list of +squares in an imperative programming language such as C++, you would assume the list is given as a kind of array. You would then iterate, or loop, an index over this array and replace each entry in the array -by the square. Right? In Scala, and in other functional -programming languages, you use maps to achieve the same. +by its square. Right? In Scala, and in other functional +programming languages, you use maps to achieve the same. A map essentially takes a function that describes how each element is transformed (in this example the function is $n \rightarrow n * n$) and @@ -961,7 +975,7 @@ \begin{center} \begin{tikzpicture} - + \node (A0) at (1.2,0) {\texttt{List(}}; \node (A1) at (2.0,0) {\texttt{1\makebox[0mm]{ ,}}}; \node (A2) at (2.9,0) {\texttt{2\makebox[0mm]{ ,}}}; @@ -991,7 +1005,7 @@ \draw [->,line width=1mm] (A7.south) -- (B7.north); \draw [->,line width=1mm] (A8.south) -- (B8.north); - \node [red] (Q0) at (-0.3,-0.3) {\large\texttt{n}}; + \node [red] (Q0) at (-0.3,-0.3) {\large\texttt{n}}; \node (Q1) at (-0.3,-0.4) {}; \node (Q2) at (-0.3,-2.5) {}; \node [red] (Q3) at (-0.3,-2.65) {\large\texttt{n\,*\,n}}; @@ -1039,8 +1053,8 @@ val res3: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) \end{lstlisting} -Let us come back to the simple example of squaring a list of numbers. -As you can see in the for-comprehensions above, we specified the list +Let us come back to the simple example of squaring a list of numbers from above. +As you can see in the for-comprehensions, we specified the list where each \code{n} comes from, namely \code{(1 to 8).toList}, and how each element needs to be transformed, the expression after the \code{yield}. This can also be expressed in a second way in Scala by @@ -1084,29 +1098,29 @@ for-comprehensions are just syntactic variants of each other, the latter can also be written as -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> for (n <- (1 to 8).toSet) yield n % 3 val res5 = Set(2, 1, 0) \end{lstlisting} -For-comprehensions can also be nested and the selection of +For-comprehensions can also be nested and the selection of elements can be guarded (or filtered). For example if we want to pair up the numbers 1 to 4 with the letters a to c, we can write \begin{lstlisting}[numbers=none] -scala> for (n <- (1 to 4).toList; +scala> for (n <- (1 to 4).toList; m <- ('a' to 'c').toList) yield (n, m) -val res6 = List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), +val res6 = List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c), (4,a), (4,b), (4,c)) \end{lstlisting} -\noindent +\noindent In this example the for-comprehension ranges over two lists, and produces a list of pairs as output. Or, if we want to find all pairs of numbers between 1 and 3 where the sum is an even number, we can write \begin{lstlisting}[numbers=none] -scala> for (n <- (1 to 3).toList; +scala> for (n <- (1 to 3).toList; m <- (1 to 3).toList; if (n + m) % 2 == 0) yield (n, m) val res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) @@ -1114,7 +1128,7 @@ \noindent The \code{if}-condition in this for-comprehension filters out all pairs where the sum is not even (therefore \code{(1, 2)}, \code{(2, -1)} and \code{(3, 2)} are not in the result because their sum is odd). +1)} and \code{(3, 2)} are not in the result because their sum is odd). To summarise, maps (or for-comprehensions) transform one collection into another. For example a list of \code{Int}s into a list of squares, and @@ -1123,7 +1137,7 @@ \begin{lstlisting}[numbers=none] scala> val cs = ('a' to 'h').toList -scala> for (n <- (0 until cs.length).toList) +scala> for (n <- (0 until cs.length).toList) yield cs(n).capitalize val res8: List[Char] = List(A, B, C, D, E, F, G, H) \end{lstlisting} @@ -1158,12 +1172,12 @@ \noindent where you need to omit the keyword \code{yield}. You can -also do more elaborate calculations before printingh such as +also do more elaborate calculations before printing such as \begin{lstlisting}[numbers=none] scala> for (n <- (1 to 5).toList) { val square = n * n - println(s"$n * $n = $square") + println(s"$n * $n = $square") } 1 * 1 = 1 2 * 2 = 4 @@ -1177,10 +1191,10 @@ \emph{string interpolation}, written \code{s"..."}. The latter is for printing out formatted strings. It allows me to refer to the integer values \code{n} and \code{square} inside a string. -This is very convenient for printing out ``things''. +This is very convenient for printing out ``things''. -The corresponding map construction for functions with -side-effects is in Scala called \code{foreach}. So you +The corresponding map construction for functions with +side-effects is in Scala called \code{foreach}. So you could also write @@ -1197,12 +1211,14 @@ 12345 \end{lstlisting} -\noindent +\noindent If you want to find out more about maps and functions with side-effects, you can ponder about the response Scala gives if you replace \code{foreach} by \code{map} in the expression above. Scala will still allow \code{map} with side-effect functions, but then reacts with a slightly interesting result. +If you understand the difference, you are pretty much on the +road of becoming a master-functional programmer. \subsection*{Aggregates} @@ -1235,9 +1251,9 @@ \code{sum}-function: \begin{lstlisting}[numbers=none] -def sum(xs: List[Int]) : Int = +def sum(xs: List[Int]) : Int = if (xs.isEmpty) 0 else xs.head + sum(xs.tail) -\end{lstlisting} +\end{lstlisting} \noindent You can then call \code{sum((1 to 8).toList)} and obtain the same result @@ -1266,7 +1282,7 @@ \begin{lstlisting}[numbers=none] def even(x: Int) : Boolean = x % 2 == 0 def odd(x: Int) : Boolean = x % 2 == 1 -\end{lstlisting} +\end{lstlisting} \noindent More interestingly, the concept of functions is really pushed to the @@ -1275,16 +1291,16 @@ quite important for making code generic. Assume a list of 10 elements: \begin{lstlisting}[numbers=none] -val lst = (1 to 10).toList -\end{lstlisting} +val lst = (1 to 10).toList +\end{lstlisting} -\noindent -Say, we want to filter out all even numbers. For this we can use +\noindent +Say, we want to filter out all even numbers. For this we can use \begin{lstlisting}[numbers=none] scala> lst.filter(even) List(2, 4, 6, 8, 10) -\end{lstlisting} +\end{lstlisting} \noindent where \code{filter} expects a function as argument specifying which @@ -1295,7 +1311,7 @@ \begin{lstlisting}[numbers=none] scala> lst.filter(odd) List(1, 3, 5, 7, 9) -\end{lstlisting} +\end{lstlisting} \noindent Such function arguments are quite frequently used for ``generic'' functions. @@ -1307,30 +1323,30 @@ 5 scala> lst.find(even) Some(2) -\end{lstlisting} +\end{lstlisting} \noindent Recall that the return type of \code{even} and \code{odd} are booleans. Such function are sometimes called predicates, because they determine what should be true for an element and what false, and then performing -some operation according to this boolean. Such predicates are quite useful. -Say you want to sort the \code{lst}-list in ascending and descending order. +some operation according to this boolean. Such predicates are quite useful. +Say you want to sort the \code{lst}-list in ascending and descending order. For this you can write \begin{lstlisting}[numbers=none] lst.sortWith(_ < _) lst.sortWith(_ > _) -\end{lstlisting} +\end{lstlisting} \noindent where \code{sortWith} expects a predicate as argument. The construction \code{_ < _} stands for a function that takes two arguments and returns true when the first one is smaller than the second. You can -think of this as elegant shorthand notation for +think of this as elegant shorthand notation for \begin{lstlisting}[numbers=none] def smaller(x: Int, y: Int) : Boolean = x < y lst.sortWith(smaller) -\end{lstlisting} +\end{lstlisting} \noindent Say you want to find in \code{lst} the first odd number greater than 2. @@ -1341,7 +1357,7 @@ \begin{lstlisting}[numbers=none] scala> lst.find(n => odd(n) && n > 2) Some(3) -\end{lstlisting} +\end{lstlisting} \noindent Here \code{n => ...} specifies a function that takes \code{n} as @@ -1352,10 +1368,10 @@ \begin{lstlisting}[numbers=none] scala> lst.find(n => odd(n) && even(n)) None -\end{lstlisting} +\end{lstlisting} While functions taking functions as arguments seems a rather useful -feature, the utility of returning a function might not be so clear. +feature, the utility of returning a function might not be so clear. I admit the following example is a bit contrived, but believe me sometims functions produce other functions in a very meaningful way. Say we want to generate functions according to strings, as in @@ -1411,7 +1427,7 @@ that do not take any (type)arguments, for example \code{Int} and \code{String}. Compound types take one or more arguments, which as seen earlier need to be given in angle-brackets, for -example \code{List[Int]} or \code{Set[List[String]]} or +example \code{List[Int]} or \code{Set[List[String]]} or \code{Map[Int, Int]}. Scala provides a basic mechanism to check the type of a (closed) @@ -1429,11 +1445,11 @@ unusable: for `things' where the type is pretty obvious, it gives an answer; but for `things' that are actually of interest (such as what is the type of a pre-defined function), it gives up with -an error message. +an error message. There are a few special type-constructors that fall outside this pattern. One is for tuples, where the type is written -with parentheses. For example +with parentheses. For example \begin{lstlisting}[ numbers=none] (Int, Int, String) @@ -1474,8 +1490,8 @@ case 0 => "zero" case 1 => "one" case 2 => "two" - case _ => "many" -} + case _ => "many" +} \end{lstlisting} \noindent It takes an integer as input argument and returns a @@ -1490,7 +1506,7 @@ \url{https://dotty.epfl.ch/api/index.html} \end{quote} -The function arrow can also be iterated, as in +The function arrow can also be iterated, as in \code{Int => String => Boolean}. This is the type for a function taking an integer as first argument and a string as second, and the result of the function is a boolean. Though silly, a @@ -1498,7 +1514,7 @@ \begin{lstlisting}[numbers=none] -def chk_string(n: Int)(s: String) : Boolean = +def chk_string(n: Int)(s: String) : Boolean = mk_string(n) == s \end{lstlisting} @@ -1536,7 +1552,7 @@ boolean. More interestingly, though, it only takes a single argument (because of the parentheses). The single argument happens to be another function (taking an integer as input and -returning a string). Remember that \code{mk_string} is just +returning a string). Remember that \code{mk_string} is just such a function. So how can we use it? For this define the somewhat silly function \code{apply_3}: @@ -1587,7 +1603,7 @@ This means we cannot fix the type of the generic traversal functions, but have to keep them \emph{polymorphic}.\footnote{Another interesting topic about -types, but we omit it here for the sake of brevity.} +types, but we omit it here for the sake of brevity.} There is one more type constructor that is rather special. It is called \code{Unit}. Recall that \code{Boolean} has two values, namely @@ -1610,7 +1626,7 @@ % \subsection*{Cool Stuff} % The first wow-moment I had with Scala was when I came across -% the following code-snippet for reading a web-page. +% the following code-snippet for reading a web-page. % \begin{lstlisting}[ numbers=none] @@ -1656,7 +1672,7 @@ % In Scala you can do better by ``hiding'' the conversion % functions. The keyword for doing this is \code{implicit} and -% it needs a built-in library called +% it needs a built-in library called % \begin{lstlisting}[numbers=none] % scala.language.implicitConversions @@ -1675,7 +1691,7 @@ % case c::s => SEQ(CHAR(c), charlist2rexp(s)) % } -% implicit def string2rexp(s: String) : Rexp = +% implicit def string2rexp(s: String) : Rexp = % charlist2rexp(s.toList) % \end{lstlisting} @@ -1720,9 +1736,9 @@ % } % \end{lstlisting} - + % \noindent This might seem a bit overly complicated, but its effect is -% that I can now write regular expressions such as $ab + ac$ +% that I can now write regular expressions such as $ab + ac$ % simply as @@ -1731,10 +1747,10 @@ % res10 = ALT(SEQ(CHAR(a),CHAR(b)),SEQ(CHAR(a),CHAR(c))) % \end{lstlisting} - + % \noindent I leave you to figure out what the other % syntactic sugar in the code above stands for. - + % One more useful feature of Scala is the ability to define % functions with varying argument lists. This is a feature that % is already present in old languages, like C, but seems to have @@ -1790,7 +1806,7 @@ %\subsection*{Coursework} \begin{figure}[p] -\begin{boxedminipage}{\textwidth} +\begin{boxedminipage}{\textwidth} \textbf{Scala Syntax for Java Developers}\bigskip \noindent @@ -1874,7 +1890,7 @@ \subsection*{More Info} There is much more to Scala than I can possibly describe in -this short document and teach in the lectures. Fortunately there are a +this short document and teach in the lectures. Fortunately there are a number of free books about Scala and of course lots of help online. For example @@ -1886,7 +1902,7 @@ \item \url{https://www.scala-exercises.org} \item \url{https://twitter.github.io/scala_school} \end{itemize} - + \noindent There is also an online course at Coursera on Functional Programming Principles in Scala by Martin Odersky, the main developer of the Scala language. And a document that explains @@ -1923,7 +1939,7 @@ \url{http://scalapuzzlers.com} and \url{http://latkin.org/blog/2017/05/02/when-the-scala-compiler-doesnt-help/} \end{center} - + Even if Scala has been a success in several high-profile companies, there is also a company (Yammer) that first used Scala in their production code, but then moved away from it. Allegedly they did not @@ -1947,7 +1963,7 @@ to iron out a number of snags from Scala 2, but why on earth are they introducing Python-esque indentation and why on earth are they re-introducing the \texttt{then}-keyword in Scala 3, when I just about got -comfortable without it? +comfortable without it? %So all in all, Scala might not be a great teaching language, %but I hope this is mitigated by the fact that I never require @@ -1969,7 +1985,7 @@ \begin{center} \url{https://www.skedulo.com/tech-blog/technology-scala-programming/} -\end{center} +\end{center} \noindent He makes pretty much the same arguments about functional programming and @@ -1986,14 +2002,14 @@ %\end{itemize} \begin{flushright}\it -There are only two kinds of languages: the ones people complain +There are only two kinds of languages: the ones people complain about\\ and the ones nobody uses.\smallskip\\ \mbox{}\hfill\small{}---Bjarne Stroustrup (the inventor of C++) \end{flushright} \end{document} -%%% Local Variables: +%%% Local Variables: %%% mode: latex %%% TeX-master: t -%%% End: +%%% End: