119 \begin{center} |
119 \begin{center} |
120 \includegraphics[scale=0.15]{../pics/vscode.png}\\[-10mm]\mbox{} |
120 \includegraphics[scale=0.15]{../pics/vscode.png}\\[-10mm]\mbox{} |
121 \end{center} |
121 \end{center} |
122 \caption{My installation of VS Code includes the following |
122 \caption{My installation of VS Code includes the following |
123 packages from Marketplace: \textbf{Scala Syntax (official)} 0.3.4, |
123 packages from Marketplace: \textbf{Scala Syntax (official)} 0.3.4, |
124 \textbf{Code Runner} 0.9.12, \textbf{Code Spell Checker} 1.7.17, |
124 \textbf{Code Runner} 0.9.13, \textbf{Code Spell Checker} 1.7.17, |
125 \textbf{Rewrap} 1.9.1 and \textbf{Subtle Match |
125 \textbf{Rewrap} 1.9.1 and \textbf{Subtle Match |
126 Brackets} 3.0.0. I have also bound the keys \keys{Ctrl} \keys{Ret} to the |
126 Brackets} 3.0.0. I have also bound the keys \keys{Ctrl} \keys{Ret} to the |
127 action ``Run-Selected-Text-In-Active-Terminal'' in order to quickly |
127 action ``Run-Selected-Text-In-Active-Terminal'' in order to quickly |
128 evaluate small code snippets in the Scala REPL. I use the internal |
128 evaluate small code snippets in the Scala REPL. I use the internal |
129 terminal to run Scala.\label{vscode}} |
129 terminal to run Scala.\label{vscode}} |
187 quite different from what you are used to in your study so far. It |
187 quite different from what you are used to in your study so far. It |
188 might even be totally alien to you. The reason is that functional |
188 might even be totally alien to you. The reason is that functional |
189 programming seems to go against the core principles of |
189 programming seems to go against the core principles of |
190 \textit{imperative programming} (which is what you do in Java and C/C++ |
190 \textit{imperative programming} (which is what you do in Java and C/C++ |
191 for example). The main idea of imperative programming is that you have |
191 for example). The main idea of imperative programming is that you have |
192 some form of \emph{state} in your program and you continuously change this |
192 some form of \emph{state} in your program and you continuously change |
193 state by issuing some commands---for example for updating a field in an |
193 this state by issuing some commands---for example for updating a field |
194 array or for adding one to a variable and so on. The classic |
194 in an array or for adding one to a variable and so on. The classic |
195 example for this style of programming is \texttt{for}-loops in C/C++. Consider |
195 example for this style of programming is a \texttt{for}-loop in C/C++. |
196 the snippet: |
196 Consider the snippet: |
197 |
197 |
198 \begin{lstlisting}[language=C,numbers=none] |
198 \begin{lstlisting}[language=C,numbers=none] |
199 for (int i = 10; i < 20; i++) { |
199 for (int i = 10; i < 20; i++) { |
200 //...do something with i... |
200 //...do something with i... |
201 } |
201 } |
207 exits. When this code is compiled and actually runs, there will be some |
207 exits. When this code is compiled and actually runs, there will be some |
208 dedicated space reserved for \texttt{i} in memory. This space of |
208 dedicated space reserved for \texttt{i} in memory. This space of |
209 typically 32 bits contains \texttt{i}'s current value\ldots\texttt{10} |
209 typically 32 bits contains \texttt{i}'s current value\ldots\texttt{10} |
210 at the beginning, and then the content will be overwritten with |
210 at the beginning, and then the content will be overwritten with |
211 new content in every iteration. The main point here is that this kind of |
211 new content in every iteration. The main point here is that this kind of |
212 updating, or manipulating, memory is 25.806\ldots or \textbf{THE ROOT OF |
212 updating, or overwriting, of memory is 25.806\ldots or \textbf{THE ROOT OF |
213 ALL EVIL}!! |
213 ALL EVIL}!! |
214 |
214 |
215 \begin{center} |
215 \begin{center} |
216 \includegraphics[scale=0.25]{../pics/root-of-all-evil.png} |
216 \includegraphics[scale=0.25]{../pics/root-of-all-evil.png} |
217 \end{center} |
217 \end{center} |
222 that gets run instruction by instruction...nicely one after another. |
222 that gets run instruction by instruction...nicely one after another. |
223 This kind of running code uses a single core of your CPU and goes as |
223 This kind of running code uses a single core of your CPU and goes as |
224 fast as your CPU frequency, also called clock-speed, allows. The problem |
224 fast as your CPU frequency, also called clock-speed, allows. The problem |
225 is that this clock-speed has not much increased over the past decade and |
225 is that this clock-speed has not much increased over the past decade and |
226 no dramatic increases are predicted for any time soon. So you are a bit |
226 no dramatic increases are predicted for any time soon. So you are a bit |
227 stuck, unlike previous generations of developers who could rely upon the |
227 stuck. This is unlike previous generations of developers who could rely |
228 fact that every 2 years or so their code would run twice as fast (in |
228 upon the fact that every 2 years or so their code would run twice as |
229 ideal circumstances) because the clock-speed of their CPUs got twice as |
229 fast because the clock-speed of their CPUs got twice as fast. |
230 fast. This unfortunately does not happen any more nowadays. To get you |
230 Unfortunately this does not happen any more nowadays. To get you out of |
231 out of this dreadful situation, CPU producers pile more and more |
231 this dreadful situation, CPU producers pile more and more cores into |
232 cores into CPUs in order to make them more powerful and potentially make |
232 CPUs in order to make them more powerful and potentially make software |
233 software faster. The task for you as developer is to take somehow |
233 faster. The task for you as developer is to take somehow advantage of |
234 advantage of these cores by running as much of your code as possible in |
234 these cores by running as much of your code as possible in parallel on |
235 parallel on as many cores you have available (typically 4 in modern |
235 as many cores you have available (typically 4 in modern laptops and |
236 laptops and sometimes much more on high-end machines). In this |
236 sometimes much more on high-end machines). In this situation, |
237 situation, \textit{mutable} variables like \texttt{i} above are evil, or |
237 \textit{mutable} variables like \texttt{i} above are evil, or at least a |
238 at least a major nuisance: Because if you want to distribute some of the |
238 major nuisance: Because if you want to distribute some of the |
239 loop-iterations over the cores that are currently idle in your system, |
239 loop-iterations over the cores that are currently idle in your system, |
240 you need to be extremely careful about who can read and overwrite |
240 you need to be extremely careful about who can read and overwrite the |
241 the variable \texttt{i}.\footnote{If you are of the mistaken belief that nothing |
241 variable \texttt{i}.\footnote{If you are of the mistaken belief that |
242 nasty can happen to \texttt{i} inside the \texttt{for}-loop, then you |
242 nothing nasty can happen to \texttt{i} inside the \texttt{for}-loop, |
243 need to go back over the C++ material.} Especially the writing operation |
243 then you need to go back over the C++ material.} Especially the writing |
244 is critical because you do not want that conflicting writes mess about |
244 operation is critical because you do not want that conflicting writes |
245 with \texttt{i}. Take my word: an untold amount of misery has arisen |
245 mess about with \texttt{i}. Take my word: an untold amount of misery has |
246 from this problem. The catch is that if you try to solve this problem in |
246 arisen from this problem. The catch is that if you try to solve this |
247 C/C++ or Java, and be as defensive as possible about reads and writes to |
247 problem in C/C++ or Java, and be as defensive as possible about reads |
248 \texttt{i}, then you need to synchronise access to it. The result is that |
248 and writes to \texttt{i}, then you need to synchronise access to it. The |
249 very often your program waits more than it runs, thereby |
249 result is that very often your program waits more than it runs, thereby |
250 defeating the point of trying to run the program in parallel in the |
250 defeating the point of trying to run the program in parallel in the |
251 first place. If you are less defensive, then usually all hell breaks |
251 first place. If you are less defensive, then usually all hell breaks |
252 loose by seemingly obtaining random results. And forget the idea of |
252 loose by seemingly obtaining random results. And forget the idea of |
253 being able to debug such code. |
253 being able to debug such code. |
254 |
254 |
357 40(!) years. See |
357 40(!) years. See |
358 \url{http://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html}. |
358 \url{http://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html}. |
359 Automatic garbage collection was included in Java in 1995; the |
359 Automatic garbage collection was included in Java in 1995; the |
360 functional language LISP had this already in 1958. Generics were added |
360 functional language LISP had this already in 1958. Generics were added |
361 to Java 5 in 2004; the functional language SML had it since 1990. |
361 to Java 5 in 2004; the functional language SML had it since 1990. |
362 Higher-order functions were added to C$\sharp$ in 2007, to Java 8 in |
362 Higher-order functions were added to C\# in 2007, to Java 8 in |
363 2014; again LISP had them since 1958. Also Rust, a C-like programming |
363 2014; again LISP had them since 1958. Also Rust, a C-like programming |
364 language that has been developed since 2010 and is gaining quite some |
364 language that has been developed since 2010 and is gaining quite some |
365 interest, borrows many ideas from functional programming from |
365 interest, borrows many ideas from functional programming from |
366 yesteryear.} |
366 yesteryear.}\medskip |
367 |
367 |
|
368 \noindent |
|
369 If you need any after-work distractions, you might have fun reading this |
|
370 about FP (functional programming): |
|
371 |
|
372 \begin{quote} |
|
373 \url{https://medium.com/better-programming/fp-toy-7f52ea0a947e} |
|
374 \end{quote} |
368 |
375 |
369 \subsection*{The Very Basics} |
376 \subsection*{The Very Basics} |
370 |
377 |
371 One advantage of Scala over Java is that it includes an interpreter (a |
378 One advantage of Scala over Java is that it includes an interpreter (a |
372 REPL, or |
379 REPL, or |
617 function is the value that will be returned. Consider the following |
624 function is the value that will be returned. Consider the following |
618 example:\footnote{We could have written this function in just one line, |
625 example:\footnote{We could have written this function in just one line, |
619 but for the sake of argument lets keep the two intermediate values.} |
626 but for the sake of argument lets keep the two intermediate values.} |
620 |
627 |
621 \begin{lstlisting}[numbers=none] |
628 \begin{lstlisting}[numbers=none] |
622 def iaverage(xs: List[Int]) : Int = { |
629 def average(xs: List[Int]) : Int = { |
623 val s = xs.sum |
630 val s = xs.sum |
624 val n = xs.length |
631 val n = xs.length |
625 s / n |
632 s / n |
626 } |
633 } |
627 \end{lstlisting} |
634 \end{lstlisting} |
628 |
635 |
629 \noindent In this example the expression \code{s / n} is in the last |
636 \noindent In this example the expression \code{s / n} is in the last |
630 line of the function---so this will be the result the function |
637 line of the function---so this will be the result the function |
631 calculates. The two lines before just calculate intermediate values. |
638 calculates. The two lines before just calculate intermediate values. |
632 This principle of the `last-line' comes in handy when you need to print |
639 This principle of the ``last-line'' comes in handy when you need to print |
633 out values, for example, for debugging purposes. Suppose you want |
640 out values, for example, for debugging purposes. Suppose you want |
634 rewrite the function as |
641 rewrite the function as |
635 |
642 |
636 \begin{lstlisting}[numbers=none] |
643 \begin{lstlisting}[numbers=none] |
637 def iaverage(xs: List[Int]) : Int = { |
644 def average(xs: List[Int]) : Int = { |
638 val s = xs.sum |
645 val s = xs.sum |
639 val n = xs.length |
646 val n = xs.length |
640 val h = xs.head |
647 val h = xs.head |
641 println(s"Input $xs with first element $h") |
648 println(s"Input $xs with first element $h") |
642 s / n |
649 s / n |
648 The \code{println} before just prints out some information about the |
655 The \code{println} before just prints out some information about the |
649 input of this function, but does not contribute to the result of the |
656 input of this function, but does not contribute to the result of the |
650 function. Similarly, the value \code{h} is used in the \code{println} |
657 function. Similarly, the value \code{h} is used in the \code{println} |
651 but does not contribute to what integer is returned. However note that |
658 but does not contribute to what integer is returned. However note that |
652 the idea with the ``last line'' is only a rough rule-of-thumb. A better |
659 the idea with the ``last line'' is only a rough rule-of-thumb. A better |
653 rule is probably, the last expression that is evaluated in the function. |
660 rule might be: the last expression that is evaluated in the function. |
654 Consider the following version of \code{iaverage}: |
661 Consider the following version of \code{iaverage}: |
655 |
662 |
656 \begin{lstlisting}[numbers=none] |
663 \begin{lstlisting}[numbers=none] |
657 def iaverage(xs: List[Int]) : Int = { |
664 def average(xs: List[Int]) : Int = { |
658 if (xs.length == 0) 0 |
665 if (xs.length == 0) 0 |
659 else xs.sum / xs.length |
666 else xs.sum / xs.length |
660 } |
667 } |
661 \end{lstlisting} |
668 \end{lstlisting} |
662 |
669 |
669 empty-case). |
676 empty-case). |
670 |
677 |
671 Summing up, do not use \code{return} in your Scala code! A function |
678 Summing up, do not use \code{return} in your Scala code! A function |
672 returns what is evaluated by the function as the last expression. There |
679 returns what is evaluated by the function as the last expression. There |
673 is always only one such last expression. Previous expressions might |
680 is always only one such last expression. Previous expressions might |
674 calculate intermediate values, but they are not returned. |
681 calculate intermediate values, but they are not returned. If your |
675 |
682 function is supposed to return multiple things, then one way in Scala is |
676 \subsection*{Loops, or better the Absence thereof} |
683 to use tuples. For example returning the minimum, average and maximum |
|
684 can be achieved by |
|
685 |
|
686 \begin{lstlisting}[numbers=none] |
|
687 def avr_minmax(xs: List[Int]) : (Int, Int, Int) = { |
|
688 if (xs.length == 0) (0, 0, 0) |
|
689 else (xs.min, xs.sum / xs.length, xs.max) |
|
690 } |
|
691 \end{lstlisting} |
|
692 |
|
693 \noindent |
|
694 which still satisfies the rule-of-thumb. |
|
695 |
|
696 |
|
697 \subsection*{Loops, or Better the Absence Thereof} |
677 |
698 |
678 Coming from Java or C/C++, you might be surprised that Scala does |
699 Coming from Java or C/C++, you might be surprised that Scala does |
679 not really have loops. It has instead, what is in functional |
700 not really have loops. It has instead, what is in functional |
680 programming called, \emph{maps}. To illustrate how they work, |
701 programming called, \emph{maps}. To illustrate how they work, |
681 let us assume you have a list of numbers from 1 to 8 and want to |
702 let us assume you have a list of numbers from 1 to 8 and want to |
729 \draw [->,line width=1mm] (A5.south) -- (B5.north); |
750 \draw [->,line width=1mm] (A5.south) -- (B5.north); |
730 \draw [->,line width=1mm] (A6.south) -- (B6.north); |
751 \draw [->,line width=1mm] (A6.south) -- (B6.north); |
731 \draw [->,line width=1mm] (A7.south) -- (B7.north); |
752 \draw [->,line width=1mm] (A7.south) -- (B7.north); |
732 \draw [->,line width=1mm] (A8.south) -- (B8.north); |
753 \draw [->,line width=1mm] (A8.south) -- (B8.north); |
733 |
754 |
734 \node [red] (Q0) at (-0.3,0) {\large\texttt{n}}; |
755 \node [red] (Q0) at (-0.3,-0.3) {\large\texttt{n}}; |
735 \node (Q1) at (-0.3,-0.1) {}; |
756 \node (Q1) at (-0.3,-0.4) {}; |
736 \node (Q2) at (-0.3,-2.8) {}; |
757 \node (Q2) at (-0.3,-2.5) {}; |
737 \node [red] (Q3) at (-0.3,-2.95) {\large\texttt{n\,*\,n}}; |
758 \node [red] (Q3) at (-0.3,-2.65) {\large\texttt{n\,*\,n}}; |
738 \draw [->,red,line width=1mm] (Q1.south) -- (Q2.north); |
759 \draw [->,red,line width=1mm] (Q1.south) -- (Q2.north); |
739 |
760 |
740 \node [red] at (-1.3,-1.5) {\huge{}\it\textbf{map}}; |
761 \node [red] at (-1.3,-1.5) {\huge{}\it\textbf{map}}; |
741 \end{tikzpicture} |
762 \end{tikzpicture} |
742 \end{center} |
763 \end{center} |
743 |
764 |
744 \noindent |
765 \noindent |
745 On top is the ``input'' list we want to transform; on the left is the |
766 On top is the ``input'' list we want to transform; on the left is the |
746 ``map'' function for how to transform each element in the input list |
767 ``map'' function for how to transform each element in the input list |
747 (the square function in this case); at the bottom is the result list of |
768 (the square function in this case); at the bottom is the result list of |
748 the map. This means that a map produces a \emph{new} list, unlike a |
769 the map. This means that a map generates a \emph{new} list, unlike a |
749 for-loop in Java or C/C++ which would most likely just update the |
770 for-loop in Java or C/C++ which would most likely just update the |
750 existing list. |
771 existing list/array. |
751 |
772 |
752 Now there are two ways to express such maps in Scala. The first way is |
773 Now there are two ways for expressing such maps in Scala. The first way is |
753 called a \emph{for-comprehension}. The keywords are \code{for} and |
774 called a \emph{for-comprehension}. The keywords are \code{for} and |
754 \code{yield}. Squaring the numbers from 1 to 8 with a for-comprehension |
775 \code{yield}. Squaring the numbers from 1 to 8 with a for-comprehension |
755 would look as follows: |
776 would look as follows: |
756 |
777 |
757 \begin{lstlisting}[numbers=none] |
778 \begin{lstlisting}[numbers=none] |
758 scala> for (n <- (1 to 8).toList) yield n * n |
779 scala> for (n <- (1 to 8).toList) yield n * n |
759 res2: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) |
780 res2: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) |
760 \end{lstlisting} |
781 \end{lstlisting} |
761 |
782 |
762 \noindent This for-comprehension states that from the list of numbers |
783 \noindent This for-comprehension states that from the list of numbers |
763 we draw elements that are given the name \code{n} (which can be |
784 we draw some elements. We use the name \code{n} to range over these |
764 arbitrary, not just \code{n}) and compute the result of \code{n * n}. |
785 elements (whereby the name is arbitrary; we could use something more |
765 This way of writing a map resembles a bit the for-loops from imperative |
786 descriptive if we wanted to). Using \code{n} we compute the result of |
766 languages, even though the idea behind for-loops and for-comprehensions |
787 \code{n * n} after the \code{yield}. This way of writing a map resembles |
767 is quite different. Also, this is a simple example---what comes after |
788 a bit the for-loops from imperative languages, even though the ideas |
768 \code{yield} can be a complex expression enclosed in \texttt{\{...\}}. |
789 behind for-loops and for-comprehensions are quite different. Also, this |
769 A more complicated example might be |
790 is a simple example---what comes after \code{yield} can be a complex |
|
791 expression enclosed in \texttt{\{...\}}. A more complicated example |
|
792 might be |
770 |
793 |
771 \begin{lstlisting}[numbers=none] |
794 \begin{lstlisting}[numbers=none] |
772 scala> for (n <- (1 to 8).toList) yield { |
795 scala> for (n <- (1 to 8).toList) yield { |
773 val i = n + 1 |
796 val i = n + 1 |
774 val j = n - 1 |
797 val j = n - 1 |
788 \end{lstlisting} |
811 \end{lstlisting} |
789 |
812 |
790 \noindent In this way, the expression \code{n => n * n} stands for the |
813 \noindent In this way, the expression \code{n => n * n} stands for the |
791 function that calculates the square (this is how the \code{n}s are |
814 function that calculates the square (this is how the \code{n}s are |
792 transformed by the map). It might not be obvious, but |
815 transformed by the map). It might not be obvious, but |
793 for-comprehensions above are just syntactic sugar: when compiling such |
816 the for-comprehensions above are just syntactic sugar: when compiling such |
794 code, Scala translates for-comprehensions into equivalent maps. This |
817 code, Scala translates for-comprehensions into equivalent maps. This |
795 even works when for-comprehensions get more complicated (see below). |
818 even works when for-comprehensions get more complicated (see below). |
796 |
819 |
797 The very charming feature of Scala is that such maps or |
820 The very charming feature of Scala is that such maps or |
798 for-comprehensions can be written for any kind of data collection, such |
821 for-comprehensions can be written for any kind of data collection, such |
837 (3,a), (3,b), (3,c), (4,a), (4,b), (4,c)) |
860 (3,a), (3,b), (3,c), (4,a), (4,b), (4,c)) |
838 \end{lstlisting} |
861 \end{lstlisting} |
839 |
862 |
840 \noindent |
863 \noindent |
841 In this example the for-comprehension ranges over two lists, and |
864 In this example the for-comprehension ranges over two lists, and |
842 produces a list of pairs as output. Or if we want to find all pairs of |
865 produces a list of pairs as output. Or, if we want to find all pairs of |
843 numbers between 1 and 3 where the sum is an even number, we can write |
866 numbers between 1 and 3 where the sum is an even number, we can write |
844 |
867 |
845 \begin{lstlisting}[numbers=none] |
868 \begin{lstlisting}[numbers=none] |
846 scala> for (n <- (1 to 3).toList; |
869 scala> for (n <- (1 to 3).toList; |
847 m <- (1 to 3).toList; |
870 m <- (1 to 3).toList; |
848 if (n + m) % 2 == 0) yield (n, m) |
871 if (n + m) % 2 == 0) yield (n, m) |
849 res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) |
872 res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) |
850 \end{lstlisting} |
873 \end{lstlisting} |
851 |
874 |
852 \noindent The \code{if}-condition in this for-comprehension filters out |
875 \noindent The \code{if}-condition in this for-comprehension filters out |
853 all pairs where the sum is not even (therefore \code{(1, 2)} is not in |
876 all pairs where the sum is not even (therefore \code{(1, 2)}, \code{(2, |
854 the result because the sum is odd). |
877 1)} and \code{(3, 2)} are not in the result because their sum is odd). |
855 |
878 |
856 To sum up, maps (or for-comprehensions) transform one collection into |
879 To sum up, maps (or for-comprehensions) transform one collection into |
857 another. For example a list of \code{Int}s into a list of squares, and |
880 another. For example a list of \code{Int}s into a list of squares, and |
858 so on. There is no need for for-loops in Scala. But please do not be |
881 so on. There is no need for for-loops in Scala. But please do not be |
859 tempted to write anything like |
882 tempted to write anything like |
864 yield cs(n).capitalize |
887 yield cs(n).capitalize |
865 res8: List[Char] = List(A, B, C, D, E, F, G, H) |
888 res8: List[Char] = List(A, B, C, D, E, F, G, H) |
866 \end{lstlisting} |
889 \end{lstlisting} |
867 |
890 |
868 \noindent |
891 \noindent |
869 This is accepted Scala-code, but utterly bad style. It can be written |
892 This is accepted Scala-code, but utterly bad style (it is more like |
870 much clearer as: |
893 Java). It can be written much clearer as: |
871 |
894 |
872 \begin{lstlisting}[numbers=none] |
895 \begin{lstlisting}[numbers=none] |
873 scala> val cs = ('a' to 'h').toList |
896 scala> val cs = ('a' to 'h').toList |
874 scala> for (c <- cs) yield c.capitalize |
897 scala> for (c <- cs) yield c.capitalize |
875 res9: List[Char] = List(A, B, C, D, E, F, G, H) |
898 res9: List[Char] = List(A, B, C, D, E, F, G, H) |
943 |
966 |
944 \subsection*{Aggregates} |
967 \subsection*{Aggregates} |
945 |
968 |
946 There is one more usage of for-loops in Java, C/C++ and the like: |
969 There is one more usage of for-loops in Java, C/C++ and the like: |
947 sometimes you want to \emph{aggregate} something about a list, for |
970 sometimes you want to \emph{aggregate} something about a list, for |
948 example to sum up all its elements. In this case you cannot use map, |
971 example summing up all its elements. In this case you cannot use map, |
949 because maps \emph{transform} one data collection into another data |
972 because maps \emph{transform} one data collection into another data |
950 collection. They cannot be used to generate a single integer |
973 collection. They cannot be used to generate a single integer |
951 representing an aggregate. So how is this done in Scala? Let us |
974 representing an aggregate. So how is this done in Scala? Let us |
952 suppose you want to sum up all elements from a list. You might |
975 suppose you want to sum up all elements from a list. You might |
953 be tempted to write something like |
976 be tempted to write something like |
1036 def quo_rem(m: Int, n: Int) : (Int, Int) = (m / n, m % n) |
1059 def quo_rem(m: Int, n: Int) : (Int, Int) = (m / n, m % n) |
1037 \end{lstlisting} |
1060 \end{lstlisting} |
1038 |
1061 |
1039 |
1062 |
1040 \noindent Since this function returns a pair of integers, its |
1063 \noindent Since this function returns a pair of integers, its |
1041 return type needs to be of type \code{(Int, Int)}. |
1064 \emph{return type} needs to be of type \code{(Int, Int)}. Incidentally, |
1042 Incidentally, this is also the input type of this function. |
1065 this is also the \emph{input type} of this function. For this notice |
1043 Notice this function takes \emph{two} arguments, namely |
1066 \code{quo_rem} takes \emph{two} arguments, namely \code{m} and \code{n}, |
1044 \code{m} and \code{n}, both of which are integers. They are |
1067 both of which are integers. They are ``packaged'' in a pair. |
1045 ``packaged'' in a pair. Consequently the complete type of |
1068 Consequently the complete type of \code{quo_rem} is |
1046 \code{quo_rem} is |
|
1047 |
1069 |
1048 \begin{lstlisting}[ numbers=none] |
1070 \begin{lstlisting}[ numbers=none] |
1049 (Int, Int) => (Int, Int) |
1071 (Int, Int) => (Int, Int) |
1050 \end{lstlisting} |
1072 \end{lstlisting} |
1051 |
1073 |
1052 Another special type-constructor is for functions, written as |
1074 This uses another special type-constructor, written as the arrow |
1053 the arrow \code{=>}. For example, the type \code{Int => |
1075 \code{=>}. For example, the type \code{Int => String} is for a function |
1054 String} is for a function that takes an integer as input |
1076 that takes an integer as input argument and produces a string as result. |
1055 argument and produces a string as result. A function of this |
1077 A function of this type is for instance |
1056 type is for instance |
|
1057 |
1078 |
1058 \begin{lstlisting}[numbers=none] |
1079 \begin{lstlisting}[numbers=none] |
1059 def mk_string(n: Int) : String = n match { |
1080 def mk_string(n: Int) : String = n match { |
1060 case 0 => "zero" |
1081 case 0 => "zero" |
1061 case 1 => "one" |
1082 case 1 => "one" |