582 def fact(n: Int) : Int = |
587 def fact(n: Int) : Int = |
583 if (n == 0) 1 else n * fact(n - 1) |
588 if (n == 0) 1 else n * fact(n - 1) |
584 \end{lstlisting} |
589 \end{lstlisting} |
585 |
590 |
586 \noindent |
591 \noindent |
587 We could also have written this as |
592 We could also have written this with braces as |
588 |
593 |
589 \begin{lstlisting}[numbers=none] |
594 \begin{lstlisting}[numbers=none] |
590 def fact(n: Int) : Int = { |
595 def fact(n: Int) : Int = { |
591 if (n == 0) 1 |
596 if (n == 0) 1 |
592 else n * fact(n - 1) |
597 else n * fact(n - 1) |
593 } |
598 } |
594 \end{lstlisting} |
599 \end{lstlisting} |
595 |
600 |
596 \noindent |
601 \noindent |
597 but this seems a bit over-kill for a small function like \code{fact}. |
602 but this seems a bit overkill for a small function like \code{fact}. |
598 Note that Scala does not have a \code{then}-keyword in an \code{if}-statement. |
603 Note that Scala does not have a \code{then}-keyword in an \code{if}-statement. |
599 Note also that there are a few other ways of how to define a function. We |
604 Note also that there are a few other ways of how to define a function. We |
600 will see some in the next sections. |
605 will see some of them in the next sections. |
|
606 |
|
607 Before we go on, let me explain one tricky point in function |
|
608 definitions, especially in larger definitions. What does a Scala function |
|
609 actually return? Scala has a \code{return} keyword, but it is |
|
610 used for something different than in Java (and C/C++). Therefore please |
|
611 make sure no \code{return} slips into your Scala code. |
|
612 |
|
613 So in the absence of \code{return}, what value does a Scala function |
|
614 actually produce? A rule-of-thumb is whatever is in the last line of the |
|
615 function is the value that will be returned. Consider the following |
|
616 example:\footnote{We could have written this function in just one line, |
|
617 but for the sake of argument lets keep the two intermediate values.} |
|
618 |
|
619 \begin{lstlisting}[numbers=none] |
|
620 def iaverage(xs: List[Int]) : Int = { |
|
621 val s = xs.sum |
|
622 val n = xs.length |
|
623 s / n |
|
624 } |
|
625 \end{lstlisting} |
|
626 |
|
627 \noindent In this example the expression \code{s / n} is in the last |
|
628 line of the function---so this will be the result the function |
|
629 calculates. The two lines before just calculate intermediate values. |
|
630 This principle of the `last-line' comes in handy when you need to print |
|
631 out values, for example, for debugging purposes. Suppose you want |
|
632 rewrite the function as |
|
633 |
|
634 \begin{lstlisting}[numbers=none] |
|
635 def iaverage(xs: List[Int]) : Int = { |
|
636 val s = xs.sum |
|
637 val n = xs.length |
|
638 val h = xs.head |
|
639 println(s"Input $xs with first element $h") |
|
640 s / n |
|
641 } |
|
642 \end{lstlisting} |
|
643 |
|
644 \noindent |
|
645 Here the function still only returns the expression in the last line. |
|
646 The \code{println} before just prints out some information about the |
|
647 input of this function, but does not contribute to the result of the |
|
648 function. Similarly, the value \code{h} is used in the \code{println} |
|
649 but does not contribute to what integer is returned. However note that |
|
650 the idea with the ``last line'' is only a rough rule-of-thumb. A better |
|
651 rule is probably, the last expression that is evaluated in the function. |
|
652 Consider the following version of \code{iaverage}: |
|
653 |
|
654 \begin{lstlisting}[numbers=none] |
|
655 def iaverage(xs: List[Int]) : Int = { |
|
656 if (xs.length == 0) 0 |
|
657 else xs.sum / xs.length |
|
658 } |
|
659 \end{lstlisting} |
|
660 |
|
661 \noindent |
|
662 What does this function return? Well are two possibilities: either the |
|
663 result of \code{xs.sum / xs.length} in the last line provided the list |
|
664 \code{xs} is nonempty, \textbf{or} if the list is empty, then it will |
|
665 return \code{0} from the \code{if}-branch (which is technically not the |
|
666 last line, but the last expression evaluated by the function in the |
|
667 empty-case). |
|
668 |
|
669 Summing up, do not use \code{return} in your Scala code! A function |
|
670 returns what is evaluated by the function as the last expression. There |
|
671 is always only one such last expression. Previous expressions might |
|
672 calculate intermediate values, but they are not returned. |
601 |
673 |
602 \subsection*{Loops, or better the Absence thereof} |
674 \subsection*{Loops, or better the Absence thereof} |
603 |
675 |
604 Coming from Java or C++, you might be surprised that Scala does |
676 Coming from Java or C/C++, you might be surprised that Scala does |
605 not really have loops. It has instead, what is in functional |
677 not really have loops. It has instead, what is in functional |
606 programming called, \emph{maps}. To illustrate how they work, |
678 programming called, \emph{maps}. To illustrate how they work, |
607 let us assume you have a list of numbers from 1 to 8 and want to |
679 let us assume you have a list of numbers from 1 to 8 and want to |
608 build the list of squares. The list of numbers from 1 to 8 |
680 build the list of squares. The list of numbers from 1 to 8 |
609 can be constructed in Scala as follows: |
681 can be constructed in Scala as follows: |
618 the list is given as a kind of array. You would then iterate, or loop, |
690 the list is given as a kind of array. You would then iterate, or loop, |
619 an index over this array and replace each entry in the array |
691 an index over this array and replace each entry in the array |
620 by the square. Right? In Scala, and in other functional |
692 by the square. Right? In Scala, and in other functional |
621 programming languages, you use maps to achieve the same. |
693 programming languages, you use maps to achieve the same. |
622 |
694 |
623 A map essentially takes a function that describes how each |
695 A map essentially takes a function that describes how each element is |
624 element is transformed (for example squared) and a list over |
696 transformed (in this example the function is $n \rightarrow n * n$) and |
625 which this function should work. There are two forms to |
697 a list over which this function should work. Pictorially you can think |
626 express such maps in Scala. The first way is called a |
698 of the idea behind maps as follows: |
627 \emph{for-comprehension}. Squaring the numbers from 1 to 8 |
699 |
|
700 \begin{center} |
|
701 \begin{tikzpicture} |
|
702 |
|
703 \node (A0) at (1.2,0) {\texttt{List(}}; |
|
704 \node (A1) at (2.0,0) {\texttt{1\makebox[0mm]{ ,}}}; |
|
705 \node (A2) at (2.9,0) {\texttt{2\makebox[0mm]{ ,}}}; |
|
706 \node (A3) at (3.8,0) {\texttt{3\makebox[0mm]{ ,}}}; |
|
707 \node (A4) at (4.7,0) {\texttt{4\makebox[0mm]{ ,}}}; |
|
708 \node (A5) at (5.6,0) {\texttt{5\makebox[0mm]{ ,}}}; |
|
709 \node (A6) at (6.5,0) {\texttt{6\makebox[0mm]{ ,}}}; |
|
710 \node (A7) at (7.4,0) {\texttt{7\makebox[0mm]{ ,}}}; |
|
711 \node (A8) at (8.3,0) {\texttt{8)}}; |
|
712 |
|
713 \node (B0) at (1.2,-3) {\texttt{List(}}; |
|
714 \node (B1) at (2.0,-3) {\texttt{1\makebox[0mm]{ ,}}}; |
|
715 \node (B2) at (3.0,-3) {\texttt{4\makebox[0mm]{ ,}}}; |
|
716 \node (B3) at (4.1,-3) {\texttt{9\makebox[0mm]{ ,}}}; |
|
717 \node (B4) at (5.2,-3) {\texttt{16\makebox[0mm]{ ,}}}; |
|
718 \node (B5) at (6.3,-3) {\texttt{25\makebox[0mm]{ ,}}}; |
|
719 \node (B6) at (7.4,-3) {\texttt{36\makebox[0mm]{ ,}}}; |
|
720 \node (B7) at (8.4,-3) {\texttt{49\makebox[0mm]{ ,}}}; |
|
721 \node (B8) at (9.4,-3) {\texttt{64\makebox[0mm]{ )}}}; |
|
722 |
|
723 \draw [->,line width=1mm] (A1.south) -- (B1.north); |
|
724 \draw [->,line width=1mm] (A2.south) -- (B2.north); |
|
725 \draw [->,line width=1mm] (A3.south) -- (B3.north); |
|
726 \draw [->,line width=1mm] (A4.south) -- (B4.north); |
|
727 \draw [->,line width=1mm] (A5.south) -- (B5.north); |
|
728 \draw [->,line width=1mm] (A6.south) -- (B6.north); |
|
729 \draw [->,line width=1mm] (A7.south) -- (B7.north); |
|
730 \draw [->,line width=1mm] (A8.south) -- (B8.north); |
|
731 |
|
732 \node [red] (Q0) at (-0.3,0) {\large\texttt{n}}; |
|
733 \node (Q1) at (-0.3,-0.1) {}; |
|
734 \node (Q2) at (-0.3,-2.8) {}; |
|
735 \node [red] (Q3) at (-0.3,-2.95) {\large\texttt{n\,*\,n}}; |
|
736 \draw [->,red,line width=1mm] (Q1.south) -- (Q2.north); |
|
737 |
|
738 \node [red] at (-1.3,-1.5) {\huge{}\it\textbf{map}}; |
|
739 \end{tikzpicture} |
|
740 \end{center} |
|
741 |
|
742 \noindent |
|
743 On top is the ``input'' list we want to transform; on the left is the |
|
744 ``map'' function for how to transform each element in the input list |
|
745 (the square function in this case); at the bottom is the result list of |
|
746 the map. This means that a map produces a \emph{new} list as a result, |
|
747 unlike a for-loop in Java or C/C++ which would most likely update the list |
|
748 exists in memory after the map. |
|
749 |
|
750 Now there are two ways to express such maps in Scala. The first way is |
|
751 called a \emph{for-comprehension}. The keywords are \code{for} and |
|
752 \code{yield}. Squaring the numbers from 1 to 8 with a for-comprehension |
628 would look as follows: |
753 would look as follows: |
629 |
754 |
630 \begin{lstlisting}[numbers=none] |
755 \begin{lstlisting}[numbers=none] |
631 scala> for (n <- (1 to 8).toList) yield n * n |
756 scala> for (n <- (1 to 8).toList) yield n * n |
632 res2: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) |
757 res2: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) |
633 \end{lstlisting} |
758 \end{lstlisting} |
634 |
759 |
635 \noindent The important keywords are \code{for} and |
760 \noindent This for-comprehension states that from the list of numbers |
636 \code{yield}. This for-comprehension roughly states that from |
761 we draw elements that are given the name \code{n} (which can be |
637 the list of numbers we draw elements that are given the name |
762 arbitrary, not just \code{n}) and compute the result of \code{n * n}. |
638 \code{n} and compute the result |
763 This way of writing a map resembles a bit the for-loops from imperative |
639 of \code{n * n}. This is a simple example---what comes after |
764 languages, even though the idea behind for-loops and for-comprehensions |
|
765 is quite different. Also, this is a simple example---what comes after |
640 \code{yield} can be a complex expression enclosed in \texttt{\{...\}}. |
766 \code{yield} can be a complex expression enclosed in \texttt{\{...\}}. |
641 As you can see, we specified the list where |
767 An example might be |
642 each \code{n} comes from, namely \code{(1 to 8).toList}, and |
768 |
643 how each element needs to be transformed. This can also be |
769 \begin{lstlisting}[numbers=none] |
644 expressed in a second way in Scala by using directly |
770 scala> for (n <- (1 to 8).toList) yield { |
645 \code{map}s as follows: |
771 val i = n + 1 |
|
772 val j = n - 1 |
|
773 i * j |
|
774 } |
|
775 res3: List[Int] = List(0, 3, 8, 15, 24, 35, 48, 63) |
|
776 \end{lstlisting} |
|
777 |
|
778 As you can see in for-comprehensions above, we specified the list where |
|
779 each \code{n} comes from, namely \code{(1 to 8).toList}, and how each |
|
780 element needs to be transformed. This can also be expressed in a second |
|
781 way in Scala by using directly the function \code{map} as follows: |
646 |
782 |
647 \begin{lstlisting}[numbers=none] |
783 \begin{lstlisting}[numbers=none] |
648 scala> (1 to 8).toList.map(n => n * n) |
784 scala> (1 to 8).toList.map(n => n * n) |
649 res3 = List(1, 4, 9, 16, 25, 36, 49, 64) |
785 res3 = List(1, 4, 9, 16, 25, 36, 49, 64) |
650 \end{lstlisting} |
786 \end{lstlisting} |
651 |
787 |
652 \noindent In this way, the expression \code{n => n * n} stands |
788 \noindent In this way, the expression \code{n => n * n} stands for the |
653 for the function that calculates the square (this is how the |
789 function that calculates the square (this is how the \code{n}s are |
654 \code{n}s are transformed). This expression for functions |
790 transformed by the map). It might not be obvious, but |
655 might remind you of your lessons about the lambda-calculus |
791 for-comprehensions above are just syntactic sugar: when compiling, Scala |
656 where this would have been written as $\lambda n.\,n * n$. It |
792 translates for-comprehensions into equivalent maps. This even works when |
657 might not be obvious, but for-comprehensions are just |
793 for-comprehensions get more complicated (see below). |
658 syntactic sugar: when compiling, Scala translates |
|
659 for-comprehensions into equivalent maps. This even works |
|
660 when for-comprehensions get more complicated (see below). |
|
661 |
794 |
662 The very charming feature of Scala is that such maps or |
795 The very charming feature of Scala is that such maps or |
663 for-comprehensions can be written for any kind of data |
796 for-comprehensions can be written for any kind of data collection, such |
664 collection, such as lists, sets, vectors, options and so on. |
797 as lists, sets, vectors, options and so on. For example if we instead |
665 For example if we instead compute the remainders modulo 3 of |
798 compute the remainders modulo 3 of this list, we can write |
666 this list, we can write |
|
667 |
799 |
668 \begin{lstlisting}[numbers=none] |
800 \begin{lstlisting}[numbers=none] |
669 scala> (1 to 8).toList.map(n => n % 3) |
801 scala> (1 to 8).toList.map(n => n % 3) |
670 res4 = List(1, 2, 0, 1, 2, 0, 1, 2) |
802 res4 = List(1, 2, 0, 1, 2, 0, 1, 2) |
671 \end{lstlisting} |
803 \end{lstlisting} |
702 res6 = List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), |
834 res6 = List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), |
703 (3,a), (3,b), (3,c), (4,a), (4,b), (4,c)) |
835 (3,a), (3,b), (3,c), (4,a), (4,b), (4,c)) |
704 \end{lstlisting} |
836 \end{lstlisting} |
705 |
837 |
706 \noindent |
838 \noindent |
707 Or if we want to find all pairs of numbers between 1 and 3 |
839 In this example the for-comprehension ranges over two lists, and |
708 where the sum is an even number, we can write |
840 produces a list of pairs as output. Or if we want to find all pairs of |
|
841 numbers between 1 and 3 where the sum is an even number, we can write |
709 |
842 |
710 \begin{lstlisting}[numbers=none] |
843 \begin{lstlisting}[numbers=none] |
711 scala> for (n <- (1 to 3).toList; |
844 scala> for (n <- (1 to 3).toList; |
712 m <- (1 to 3).toList; |
845 m <- (1 to 3).toList; |
713 if (n + m) % 2 == 0) yield (n, m) |
846 if (n + m) % 2 == 0) yield (n, m) |
714 res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) |
847 res7 = List((1,1), (1,3), (2,2), (3,1), (3,3)) |
715 \end{lstlisting} |
848 \end{lstlisting} |
716 |
849 |
717 \noindent The \code{if}-condition in the for-comprehension |
850 \noindent The \code{if}-condition in this for-comprehension filters out |
718 filters out all pairs where the sum is not even. |
851 all pairs where the sum is not even (therefore \code{(1, 2)} is not in |
|
852 the result because the sum is odd). |
|
853 |
|
854 To sum up, maps (or for-comprehensions) transform one collection into |
|
855 another. For example a list of \code{Int}s into a list of squares, or a |
|
856 list of \code{Int}s into a set of \code{Int}s and so on. There is no need |
|
857 for for-loops in Scala. But please do not be tempted to write anything like |
|
858 |
|
859 \begin{lstlisting}[numbers=none] |
|
860 scala> val cs = ('a' to 'h').toList |
|
861 scala> for (n <- (0 until cs.length).toList) |
|
862 yield cs(n).capitalize |
|
863 res8: List[Char] = List(A, B, C, D, E, F, G, H) |
|
864 \end{lstlisting} |
|
865 |
|
866 \noindent |
|
867 This is accepted Scala-code, but utterly bad style. It can be written |
|
868 much clearer as: |
|
869 |
|
870 \begin{lstlisting}[numbers=none] |
|
871 scala> val cs = ('a' to 'h').toList |
|
872 scala> for (c <- cs) yield c.capitalize |
|
873 res9: List[Char] = List(A, B, C, D, E, F, G, H) |
|
874 \end{lstlisting} |
719 |
875 |
720 \subsection*{Results and Side-Effects} |
876 \subsection*{Results and Side-Effects} |
721 |
877 |
722 While hopefully this all about maps looks reasonable, there is one |
878 While hopefully this all about maps looks reasonable, there is one |
723 complication: In the examples above we always wanted to |
879 complication: In the examples above we always wanted to |