# HG changeset patch # User Christian Urban # Date 1695509384 -3600 # Node ID 86a456f8cb9261da65f37c33248a596bb880736d # Parent 48de09728447f4067b225be7e202a7c2003176c0 updated diff -r 48de09728447 -r 86a456f8cb92 IDEAS --- a/IDEAS Sat Mar 11 23:24:15 2023 +0000 +++ b/IDEAS Sat Sep 23 23:49:44 2023 +0100 @@ -1,3 +1,9 @@ +Functional programming - A radical and elegant attack on the entire +enterprise of programming. You have to rewire your brain to think about +functional programming. + +============== + flight data https://blog.jonlu.ca/posts/aa-tracker?ref=rprog diff -r 48de09728447 -r 86a456f8cb92 core_templates1/collatz.scala --- a/core_templates1/collatz.scala Sat Mar 11 23:24:15 2023 +0000 +++ b/core_templates1/collatz.scala Sat Sep 23 23:49:44 2023 +0100 @@ -10,7 +10,6 @@ //(1) def collatz(n: Long) : Long = ??? - //(2) def collatz_max(bnd: Long) : (Long, Long) = ??? @@ -21,5 +20,6 @@ def last_odd(n: Long) : Long = ??? + } diff -r 48de09728447 -r 86a456f8cb92 cws/crown.png Binary file cws/crown.png has changed diff -r 48de09728447 -r 86a456f8cb92 cws/disclaimer.sty --- a/cws/disclaimer.sty Sat Mar 11 23:24:15 2023 +0000 +++ b/cws/disclaimer.sty Sat Sep 23 23:49:44 2023 +0100 @@ -97,7 +97,7 @@ It should be understood that the work you submit represents your \textbf{own} effort! You have implemented the code entirely on your own. You have not copied from anyone else. -Do not be tempted to ask Github Copilot for help or +Do not be tempted to ask Copilot for help or do any other shenanigans like this! An exception is the Scala code I showed during the lectures or uploaded to KEATS, which you can freely use.\bigskip diff -r 48de09728447 -r 86a456f8cb92 cws/main_cw01.pdf Binary file cws/main_cw01.pdf has changed diff -r 48de09728447 -r 86a456f8cb92 handouts/pep-ho.pdf Binary file handouts/pep-ho.pdf has changed diff -r 48de09728447 -r 86a456f8cb92 handouts/pep-ho.tex --- a/handouts/pep-ho.tex Sat Mar 11 23:24:15 2023 +0000 +++ b/handouts/pep-ho.tex Sat Sep 23 23:49:44 2023 +0100 @@ -124,7 +124,7 @@ \begin{document} -\fnote{\copyright{} Christian Urban, King's College London, 2017, 2018, 2019, 2020, 2021, 2022} +\fnote{\copyright{} Christian Urban, King's College London, 2017, 2018, 2019, 2020, 2021, 2022, 2023} %\begin{tcolorbox}[breakable,size=fbox,boxrule=1pt,pad at break*=1mm,colback=cellbackground,colframe=cellborder] % abd @@ -136,6 +136,10 @@ \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\\ + + \subsection*{Introduction} \noindent @@ -150,7 +154,7 @@ ``Scala is the better Java''.\footnote{from \url{https://www.slideshare.net/maximnovak/joy-of-scala}} -A number of companies---the Guardian, Twitter, Coursera, FourSquare, +A number of companies---the Guardian, Dualingo, Coursera, FourSquare, Netflix, LinkedIn, ITV 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 @@ -168,18 +172,22 @@ \end{quote} \noindent\alert -Just make sure you are downloading the ``battle tested'' version of -Scala \textbf{2.13} This is the one I am going to use in the lectures and -in the coursework. The newer Scala 3.1 \& 3.2 still have some -features not fully implemented.\bigskip +Just make sure you are using the version 3(!) of Scala. This is +the version I am going to use in the lectures and in the coursework. This +can be any version of Scala 3.X where $X=\{1,2,3\}$. Also the minor +number does not matter. Note that this will be the first year I am +using this version -- so some hiccups are bound to happen. Apologies +in advance!\bigskip \noindent -If you are interested, there are also experimental backends of Scala -for producing code under Android (\url{http://scala-android.org}); for -generating JavaScript code (\url{https://www.scala-js.org}); and there -is work under way to have a native Scala compiler generating X86-code -(\url{http://www.scala-native.org}). Though be warned these backends -are still rather beta or even alpha. +If you are interested, there are also experimental backend of Scala +for generating JavaScript code (\url{https://www.scala-js.org}), and +there is work under way to have a native Scala compiler generating +X86-code (\url{http://www.scala-native.org}). There are also some +tricks you can play with Scala programms running as native +GraalVM~\hr{https://scala-cli.virtuslab.org/docs/cookbooks/native-images/} +images. Though be warned these backends are still rather beta or even +alpha. \subsection*{VS Code and Scala} @@ -200,7 +208,7 @@ \noindent and should already come pre-installed in the Department (together with the Scala compiler). Being a project that just started in 2015, VS Code is -relatively new and thus far from perfect. However it includes a +relatively new and therefore far from perfect. However it includes a \textit{Marketplace} from which a multitude of extensions can be downloaded that make editing and running Scala code a little easier (see Figure~\ref{vscode} for my setup). @@ -221,11 +229,12 @@ \end{boxedminipage} \end{figure} - Actually \alert last year I switched to VS Codium, which is VS Code minus -all the telemetry that is normally sent to Microsoft. Apart from the - telemetry, it works pretty much the same as the original but is driven -by a dedicated community, rather than a big company. You can download -VS Codium from +Actually \alert last year I switched to VS Codium, which is VS Code +minus all the telemetry 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 +Codium from \begin{quote} \url{https://vscodium.com} @@ -263,7 +272,7 @@ 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 million-lines codebase than with our small +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 just want to try out 20-lines of Scala code? Your mileage may vary though.~\texttt{;o)} @@ -287,16 +296,16 @@ %to inflict Scala upon you. Very likely writing programs in a functional programming language is -quite different from what you are used to in your study so far. It +quite different from what you are used to in your study so far. It might even be totally alien to you. The reason is that functional programming seems to go against the core principles of -\textit{imperative programming} (which is what you do in Java and C/C++ -for example). The main idea of imperative programming is that you have -some form of \emph{state} in your program and you continuously change -this state by issuing some commands---for example for updating a field -in an array or for adding one to a variable and so on. The classic -example for this style of programming is a \texttt{for}-loop in C/C++. -Consider the snippet: +\textit{imperative programming} (which is what you do in Java and +C/C++ for example). The main idea of imperative programming is that +you have some form of \emph{state} in your program and you +continuously change this state by issuing some commands---for example +for updating a field in an array or for adding one to a variable +stored in memory and so on. The classic example for this style of +programming is a \texttt{for}-loop in C/C++. Consider the snippet: \begin{lstlisting}[language=C,numbers=none] for (int i = 10; i < 20; i++) { @@ -304,16 +313,16 @@ } \end{lstlisting} -\noindent Here the integer variable \texttt{i} embodies the state, which -is first set to \texttt{10} and then increased by one in each -loop-iteration until it reaches \texttt{20} at which point the loop -exits. When this code is compiled and actually runs, there will be some -dedicated space reserved for \texttt{i} in memory. This space of -typically 32 bits contains \texttt{i}'s current value\ldots\texttt{10} -at the beginning, and then the content will be overwritten with -new content in every iteration. The main point here is that this kind of -updating, or overwriting, of memory is 25.806\ldots or \textbf{THE ROOT OF -ALL EVIL}!! +\noindent Here the integer variable \texttt{i} embodies part of the +state of the program, which is first set to \texttt{10} and then +increased by one in each loop-iteration until it reaches \texttt{20} +at which point the loop exits. When this code is compiled and actually +runs, there will be some dedicated space reserved for \texttt{i} in +memory. This space of typically 32 bits contains \texttt{i}'s current +value\ldots\texttt{10} at the beginning, and then the content will be +overwritten with new content in every iteration. The main point here +is that this kind of updating, or overwriting, of memory is +25.806\ldots or \textbf{THE ROOT OF ALL EVIL}!! \begin{center} \includegraphics[scale=0.25]{../pics/root-of-all-evil.png} @@ -336,7 +345,7 @@ CPUs in order to make them more powerful and potentially make software faster. The task for you as developer is to take somehow advantage of these cores by running as much of your code as possible in parallel on -as many cores you have available (typically 4 or more in modern laptops +as many cores you have available (typically 4-8 or even more in modern laptops and sometimes much more on high-end machines). In this situation \textit{mutable} variables like \texttt{i} in the C-code above are evil, or at least a major nuisance: Because if you want to distribute some of @@ -471,43 +480,42 @@ \noindent If you need any after-work distractions, you might have fun reading -this about FP (functional programming) --- you +the following article about FP (functional programming) --- you might have to disable your browser cookies though if you want to read it for free. And spoiler alert: This is tongue-in-cheek \texttt{;o)} \begin{quote} -\url{https://betterprogramming.pub/fp-toy-7f52ea0a947e} + \url{https://archive.ph/vrofC} \end{quote} \subsection*{The Very Basics} -One advantage of Scala over Java is that it includes an interpreter (a -REPL, or +Let us get back to Scala: One advantage of Scala over Java is that it +includes an interpreter (a REPL, or \underline{R}ead-\underline{E}val-\underline{P}rint-\underline{L}oop) with which you can run and test small code snippets without the need of a compiler. This helps a lot with interactively developing -programs. It is my preferred way of writing small Scala -programs. Once you installed Scala, you can start the interpreter by -typing on the command line: +programs. It is my preferred way of writing small Scala programs. Once +you installed Scala, you can start the interpreter by typing on the +command line: \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] $ scala -Welcome to Scala 2.13.9 (OpenJDK 64-Bit Server VM, Java 17.0.1). -Type in expressions for evaluation. Or try :help. +Welcome to Scala 3.3.1 (17.0.8.1, Java OpenJDK 64-Bit Server VM). +Type in expressions for evaluation. Or try :help. scala> \end{lstlisting}%$ - - \noindent The precise response may vary depending -on the version and platform where you installed Scala. At the Scala +on the version and platform where you installed Scala. Make sure +you have installed Scala version 3. At the Scala prompt you can type things like \code{2 + 3}\;\keys{Ret} and the output will be -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> 2 + 3 -res0: Int = 5 +val res0: Int = 5 \end{lstlisting} \noindent The answer means that he result of the addition is of type @@ -515,15 +523,15 @@ Scala gives automatically to the result. You can reuse this name later on, for example -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> res0 + 4 -res1: Int = 9 +val res1: Int = 9 \end{lstlisting} \noindent Another classic example you can try out is -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> print("hello world") hello world \end{lstlisting} @@ -620,6 +628,12 @@ \subsection*{Values} +\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 + +\noindent 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 @@ -628,13 +642,13 @@ \begin{lstlisting}[numbers=none] scala> val x = 42 -x: Int = 42 +val x: Int = 42 scala> val y = 3 + 4 -y: Int = 7 +val y: Int = 7 scala> val z = x / y -z: Int = 6 +val z: Int = 6 \end{lstlisting} \noindent @@ -646,9 +660,12 @@ \begin{lstlisting}[numbers=none] scala> z = 9 -error: reassignment to val - z = 9 - ^ +-- [E052] Type Error: ----------------------------------- +1 |z = 9 + |^^^^^ + |Reassignment to val z + | ... +1 error found \end{lstlisting} \noindent @@ -709,7 +726,7 @@ 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 it +more complex, then it can be enclosed in braces, like above. If it is just a simple expression, like \code{x + 1}, you can omit the braces. Very often functions are recursive (that is call themselves), like the venerable factorial function: @@ -720,7 +737,8 @@ \end{lstlisting} \noindent -We could also have written this with braces as +where we have to give the return type \code{Int}. Note we could also +have written this with braces as \begin{lstlisting}[numbers=none] def fact(n: Int) : Int = { @@ -731,7 +749,7 @@ \noindent but this seems a bit overkill for a small function like \code{fact}. -Note that Scala does not have a \code{then}-keyword in an +Notice that Scala does not have a \code{then}-keyword in an \code{if}-statement. Also important is that there should be always an \code{else}-branch. Never write an \code{if} without an \code{else}, unless you know what you are doing! While \code{def} is the main @@ -748,7 +766,7 @@ actually produce? A rule-of-thumb is whatever is in the last line of the function is the value that will be returned. Consider the following example:\footnote{We could have written this function in just one line, -but for the sake of argument lets keep the two intermediate values.} +but for the sake of argument let's keep the two intermediate values.} \begin{lstlisting}[numbers=none] def average(xs: List[Int]) : Int = { @@ -776,11 +794,12 @@ \end{lstlisting} \noindent -Here the function still only returns the expression in the last line. -The \code{println} before just prints out some information about the -input of this function, but does not contribute to the result of the -function. Similarly, the value \code{h} is used in the \code{println} -but does not contribute to what integer is returned. +Here the function still only returns the expression \code{s / n} in +the last line. The \code{println} before just prints out some +information about the input of this function, but does not contribute +to the result of the function. Similarly, the value \code{h} is used +in the \code{println} but does not contribute to what integer is +returned by the function. A caveat is that the idea with the ``last line'' is only a rough rule-of-thumb. A better rule might be: the last expression that is @@ -820,6 +839,13 @@ \noindent which still satisfies the rule-of-thumb. +\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black] + Do not use \code{return} in your code to indicate what a function + produces as a result! It has a different meaning in Scala than in + Java. It can change the meaning of your program, and you should + never use it. +\end{tcolorbox} + \subsection*{Loops, or Better the Absence Thereof} @@ -830,9 +856,9 @@ build the list of squares. The list of numbers from 1 to 8 can be constructed in Scala as follows: -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> (1 to 8).toList -res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8) +val res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8) \end{lstlisting} \noindent Generating from this list the list of corresponding @@ -904,7 +930,7 @@ \begin{lstlisting}[numbers=none] scala> for (n <- (1 to 8).toList) yield n * n -res2: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) +val res2: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) \end{lstlisting} \noindent This for-comprehension states that from the list of numbers @@ -924,17 +950,19 @@ val j = n - 1 i * j + 1 } -res3: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) +val res3: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) \end{lstlisting} -As you can see in for-comprehensions above, we specified the list where -each \code{n} comes from, namely \code{(1 to 8).toList}, and how each -element needs to be transformed. This can also be expressed in a second -way in Scala by using directly the function \code{map} as follows: +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 +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 +using directly the function \code{map} as follows: -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> (1 to 8).toList.map(n => n * n) -res3 = List(1, 4, 9, 16, 25, 36, 49, 64) +val res3 = List(1, 4, 9, 16, 25, 36, 49, 64) \end{lstlisting} \noindent In this way, the expression \code{n => n * n} stands for the @@ -949,43 +977,41 @@ as lists, sets, vectors, options and so on. For example if we instead compute the remainders modulo 3 of this list, we can write -\begin{lstlisting}[numbers=none] +\begin{lstlisting}[numbers=none,language={}] scala> (1 to 8).toList.map(n => n % 3) -res4 = List(1, 2, 0, 1, 2, 0, 1, 2) +val res4 = List(1, 2, 0, 1, 2, 0, 1, 2) \end{lstlisting} \noindent If we, however, transform the numbers 1 to 8 not into a list, but into a set, and then compute the remainders modulo 3 we obtain -\begin{lstlisting}[numbers=none] -scala> (1 to 8).toSet[Int].map(n => n % 3) -res5 = Set(2, 1, 0) +\begin{lstlisting}[numbers=none,language={}] +scala> (1 to 8).toSet.map(n => n % 3) +val res5 = Set(2, 1, 0) \end{lstlisting} -\noindent This\footnote{This returns actually \code{HashSet(2, 1, 3)}, +\noindent This\footnote{This returns actually \code{HashSet(1, 2, 3)}, but this is just an implementation detail of how sets are implemented in Scala.} is the correct result for sets, as there are only three -equivalence classes of integers modulo 3. Note that in this example we -need to ``help'' Scala to transform the numbers into a set of integers -by explicitly annotating the type \code{Int}. Since maps and +equivalence classes of integers modulo 3. Since maps and for-comprehensions are just syntactic variants of each other, the latter can also be written as \begin{lstlisting}[numbers=none] -scala> for (n <- (1 to 8).toSet[Int]) yield n % 3 -res5 = Set(2, 1, 0) +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 -elements can be guarded. For example if we want to pair up +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; m <- ('a' to 'c').toList) yield (n, m) -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)) +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 @@ -997,7 +1023,7 @@ scala> for (n <- (1 to 3).toList; m <- (1 to 3).toList; if (n + m) % 2 == 0) yield (n, m) -res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) +val res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) \end{lstlisting} \noindent The \code{if}-condition in this for-comprehension filters out @@ -1013,7 +1039,7 @@ scala> val cs = ('a' to 'h').toList scala> for (n <- (0 until cs.length).toList) yield cs(n).capitalize -res8: List[Char] = List(A, B, C, D, E, F, G, H) +val res8: List[Char] = List(A, B, C, D, E, F, G, H) \end{lstlisting} \noindent @@ -1023,7 +1049,7 @@ \begin{lstlisting}[numbers=none] scala> val cs = ('a' to 'h').toList scala> for (c <- cs) yield c.capitalize -res9: List[Char] = List(A, B, C, D, E, F, G, H) +val res9: List[Char] = List(A, B, C, D, E, F, G, H) \end{lstlisting} \subsection*{Results and Side-Effects} @@ -1046,7 +1072,7 @@ \noindent where you need to omit the keyword \code{yield}. You can -also do more elaborate calculations such as +also do more elaborate calculations before printingh such as \begin{lstlisting}[numbers=none] scala> for (n <- (1 to 5).toList) { @@ -1063,7 +1089,7 @@ \noindent In this code I use a value assignment (\code{val square = ...} ) and also what is called in Scala a \emph{string interpolation}, written \code{s"..."}. The latter -is for printing out an equation. It allows me to refer to the +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''. @@ -1269,13 +1295,13 @@ of anything simple, but for example in the Compiler module next year I show a compilation functions that needs to generate functions as intermediate result. Anyway, notice the interesting type we had to -annotate to \code{mkfn}. Types of Scala are described next. +annotate to \code{mkfn}. The types in Scala are described next. \subsection*{Types} In most functional programming languages, types play an -important role. Scala is such a language. You have already +essential role. Scala is such a language. You have already seen built-in types, like \code{Int}, \code{Boolean}, \code{String} and \code{BigInt}, but also user-defined ones, like \code{Rexp} (see coursework). Unfortunately, types can be a thorny @@ -1302,6 +1328,23 @@ 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) +expression---closed means that all parts are already known to Scala. +Then you can use the command \code{:type} and check in the REPL: + +\begin{lstlisting}[ numbers=none] +scala> :type (1, List(3), Set(4,5), "hello") +(Int, List[Int], Set[Int], String) +\end{lstlisting} + +\noindent +If Scala can calculate the type of the given expression, then it +will print it. Unfortunately, this way of finding out a type is almost +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. + 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 @@ -1420,10 +1463,12 @@ You might ask: Apart from silly functions like above, what is the point of having functions as input arguments to other -functions? In Java there is indeed no need of this kind of -feature: at least in the past it did not allow such -constructions. I think, the point of Java 8 and successors was to lift this -restriction. But in all functional programming languages, +functions? +%In Java there is indeed no need of this kind of +%feature: at least in the past it did not allow such +%constructions. I think, the point of Java 8 and successors was to lift this +%restriction. +Well, in all functional programming languages, including Scala, it is really essential to allow functions as input argument. Above you have already seen \code{map} and \code{foreach} which need this feature. Consider the functions @@ -1698,7 +1743,7 @@ \end{lstlisting}\bigskip \noindent -Type for list of Strings: +Compound types, say the type for list of Strings: \begin{lstlisting}[language=Java] List/*!\annotation{Java}!*/ @@ -1743,7 +1788,7 @@ \subsection*{More Info} There is much more to Scala than I can possibly describe in -this 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 @@ -1766,11 +1811,13 @@ \end{itemize} While I am quite enthusiastic about Scala, I am also happy to -admit that it has more than its fair share of faults. The -problem seen earlier of having to give an explicit type to -\code{toSet}, but not \code{toList} is one of them. There are -also many ``deep'' ideas about types in Scala, which even to -me as seasoned functional programmer are puzzling. Whilst +admit that it has more than its fair share of faults. +%The +%problem seen earlier of having to give an explicit type to +%\code{toSet}, but not \code{toList} is one of them. There are +%also many ``deep'' ideas about types in Scala, which even to +%me as seasoned functional programmer are puzzling. +For example, whilst implicits are great, they can also be a source of great headaches, for example consider the code: @@ -1799,12 +1846,15 @@ language is lately developing at lightening speed (in comparison to the past) taking on many features of Scala and other languages, and it seems it even introduces -new features on its own. +new features on its own. So there is seemingly even more incentive to +stick with the old stuff you know. Scala is deep: After many years, I still continue to learn new technique -for writing more elegant code. Unfortunately, I have not yet managed to -switch over my code to Scala 3.0 due to time constraints. Scala 3 seems +for writing more elegant code. +%Unfortunately, I have not yet managed to +%switch over my code to Scala 3.0 due to time constraints. +Scala 3 seems 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 diff -r 48de09728447 -r 86a456f8cb92 main_solution3/re.scala --- a/main_solution3/re.scala Sat Mar 11 23:24:15 2023 +0000 +++ b/main_solution3/re.scala Sat Sep 23 23:49:44 2023 +0100 @@ -62,7 +62,7 @@ case SEQs(Nil) => ZERO case SEQs(r1::rs) => if (nullable(r1)) ALT(SEQs(der(c, r1)::rs), der(c, SEQs(rs))) - else SEQs(der(c, r1):: rs) + else SEQs(der(c, r1) :: rs) case STAR(r1) => SEQ(der(c, r1), STAR(r1)) } diff -r 48de09728447 -r 86a456f8cb92 main_templates1/drumb.scala --- a/main_templates1/drumb.scala Sat Mar 11 23:24:15 2023 +0000 +++ b/main_templates1/drumb.scala Sat Sep 23 23:49:44 2023 +0100 @@ -20,6 +20,7 @@ def get_january_data(symbol: String, year: Int) : List[String] = ??? + // (2) def get_first_price(symbol: String, year: Int) : Option[Double] = ??? diff -r 48de09728447 -r 86a456f8cb92 progs/lecture5.scala --- a/progs/lecture5.scala Sat Mar 11 23:24:15 2023 +0000 +++ b/progs/lecture5.scala Sat Sep 23 23:49:44 2023 +0100 @@ -271,7 +271,7 @@ // This is called "strict evaluation". -// On the contrary, say we have a pretty expensive operation: +// In contrast say we have a pretty expensive operation: def peop(n: BigInt): Boolean = peop(n + 1) @@ -394,8 +394,8 @@ enuml(1, "a") enuml(1, "a").size enuml(2, "a").size -enuml(3, "a").size // out of heap space - +enuml(3, "a").size +enuml(4, "a").size // out of heap space def enum(rs: LazyList[Rexp]) : LazyList[Rexp] = @@ -405,7 +405,7 @@ enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force -enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000).force +enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000).force // out of memory def depth(r: Rexp) : Int = r match { diff -r 48de09728447 -r 86a456f8cb92 progs/mandelbrot.scala --- a/progs/mandelbrot.scala Sat Mar 11 23:24:15 2023 +0000 +++ b/progs/mandelbrot.scala Sat Sep 23 23:49:44 2023 +0100 @@ -3,7 +3,7 @@ // // see https://en.wikipedia.org/wiki/Mandelbrot_set // -// under scala 3.2.2 needs to be called with +// needs to be called with // // scala -cp scala-parallel-collections_3-1.0.4.jar //