741 |
741 |
742 \noindent |
742 \noindent |
743 On top is the ``input'' list we want to transform; on the left is the |
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 |
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 |
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, |
746 the map. This means that a map produces a \emph{new} list, unlike a |
747 unlike a for-loop in Java or C/C++ which would most likely update the list |
747 for-loop in Java or C/C++ which would most likely just update the |
748 exists in memory after the map. |
748 existing list. |
749 |
749 |
750 Now there are two ways to express such maps in Scala. The first way is |
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 |
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 |
752 \code{yield}. Squaring the numbers from 1 to 8 with a for-comprehension |
753 would look as follows: |
753 would look as follows: |
762 arbitrary, not just \code{n}) and compute the result of \code{n * n}. |
762 arbitrary, not just \code{n}) and compute the result of \code{n * n}. |
763 This way of writing a map resembles a bit the for-loops from imperative |
763 This way of writing a map resembles a bit the for-loops from imperative |
764 languages, even though the idea behind for-loops and for-comprehensions |
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 |
765 is quite different. Also, this is a simple example---what comes after |
766 \code{yield} can be a complex expression enclosed in \texttt{\{...\}}. |
766 \code{yield} can be a complex expression enclosed in \texttt{\{...\}}. |
767 An example might be |
767 A more complicated example might be |
768 |
768 |
769 \begin{lstlisting}[numbers=none] |
769 \begin{lstlisting}[numbers=none] |
770 scala> for (n <- (1 to 8).toList) yield { |
770 scala> for (n <- (1 to 8).toList) yield { |
771 val i = n + 1 |
771 val i = n + 1 |
772 val j = n - 1 |
772 val j = n - 1 |
773 i * j |
773 i * j + 1 |
774 } |
774 } |
775 res3: List[Int] = List(0, 3, 8, 15, 24, 35, 48, 63) |
775 res3: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64) |
776 \end{lstlisting} |
776 \end{lstlisting} |
777 |
777 |
778 As you can see in for-comprehensions above, we specified the list where |
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 |
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 |
780 element needs to be transformed. This can also be expressed in a second |
786 \end{lstlisting} |
786 \end{lstlisting} |
787 |
787 |
788 \noindent In this way, the expression \code{n => n * n} stands for the |
788 \noindent In this way, the expression \code{n => n * n} stands for the |
789 function that calculates the square (this is how the \code{n}s are |
789 function that calculates the square (this is how the \code{n}s are |
790 transformed by the map). It might not be obvious, but |
790 transformed by the map). It might not be obvious, but |
791 for-comprehensions above are just syntactic sugar: when compiling, Scala |
791 for-comprehensions above are just syntactic sugar: when compiling such |
792 translates for-comprehensions into equivalent maps. This even works when |
792 code, Scala translates for-comprehensions into equivalent maps. This |
793 for-comprehensions get more complicated (see below). |
793 even works when for-comprehensions get more complicated (see below). |
794 |
794 |
795 The very charming feature of Scala is that such maps or |
795 The very charming feature of Scala is that such maps or |
796 for-comprehensions can be written for any kind of data collection, such |
796 for-comprehensions can be written for any kind of data collection, such |
797 as lists, sets, vectors, options and so on. For example if we instead |
797 as lists, sets, vectors, options and so on. For example if we instead |
798 compute the remainders modulo 3 of this list, we can write |
798 compute the remainders modulo 3 of this list, we can write |
850 \noindent The \code{if}-condition in this for-comprehension filters out |
850 \noindent The \code{if}-condition in this for-comprehension filters out |
851 all pairs where the sum is not even (therefore \code{(1, 2)} is not in |
851 all pairs where the sum is not even (therefore \code{(1, 2)} is not in |
852 the result because the sum is odd). |
852 the result because the sum is odd). |
853 |
853 |
854 To sum up, maps (or for-comprehensions) transform one collection into |
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 |
855 another. For example a list of \code{Int}s into a list of squares, and |
856 list of \code{Int}s into a set of \code{Int}s and so on. There is no need |
856 so on. There is no need for for-loops in Scala. But please do not be |
857 for for-loops in Scala. But please do not be tempted to write anything like |
857 tempted to write anything like |
858 |
858 |
859 \begin{lstlisting}[numbers=none] |
859 \begin{lstlisting}[numbers=none] |
860 scala> val cs = ('a' to 'h').toList |
860 scala> val cs = ('a' to 'h').toList |
861 scala> for (n <- (0 until cs.length).toList) |
861 scala> for (n <- (0 until cs.length).toList) |
862 yield cs(n).capitalize |
862 yield cs(n).capitalize |
874 \end{lstlisting} |
874 \end{lstlisting} |
875 |
875 |
876 \subsection*{Results and Side-Effects} |
876 \subsection*{Results and Side-Effects} |
877 |
877 |
878 While hopefully this all about maps looks reasonable, there is one |
878 While hopefully this all about maps looks reasonable, there is one |
879 complication: In the examples above we always wanted to |
879 complication: In the examples above we always wanted to transform one |
880 transform one list into another list (e.g.~list of squares), |
880 list into another list (e.g.~list of squares), or one set into another |
881 or one set into another set (set of numbers into set of |
881 set (set of numbers into set of remainders modulo 3). What happens if we |
882 remainders modulo 3). What happens if we just want to print out |
882 just want to print out a list of integers? In these cases the |
883 a list of integers? Then actually the for-comprehension |
883 for-comprehensions need to be modified. The reason is that \code{print}, |
884 needs to be modified. The reason is that \code{print}, you |
884 you guessed it, does not produce any result, but only produces what is |
885 guessed it, does not produce any result, but only produces |
885 in the functional-programming-lingo called a \emph{side-effect}\ldots it |
886 what is in the functional-programming-lingo called a |
886 prints something out on the screen. Printing out the list of numbers |
887 \emph{side-effect}. Printing out the list of numbers from 1 to 5 |
887 from 1 to 5 would look as follows |
888 would look as follows |
|
889 |
888 |
890 \begin{lstlisting}[numbers=none] |
889 \begin{lstlisting}[numbers=none] |
891 scala> for (n <- (1 to 5).toList) print(n) |
890 scala> for (n <- (1 to 5).toList) print(n) |
892 12345 |
891 12345 |
893 \end{lstlisting} |
892 \end{lstlisting} |
931 \begin{lstlisting}[numbers=none] |
930 \begin{lstlisting}[numbers=none] |
932 scala> (1 to 5).toList.foreach(print) |
931 scala> (1 to 5).toList.foreach(print) |
933 12345 |
932 12345 |
934 \end{lstlisting} |
933 \end{lstlisting} |
935 |
934 |
936 \noindent Again I hope this reminds you a bit of your |
935 \noindent |
937 lambda-calculus lessons, where an explanation is given why |
|
938 both forms produce the same result. |
|
939 |
|
940 |
|
941 If you want to find out more about maps and functions with |
936 If you want to find out more about maps and functions with |
942 side-effects, you can ponder about the response Scala gives if |
937 side-effects, you can ponder about the response Scala gives if |
943 you replace \code{foreach} by \code{map} in the expression |
938 you replace \code{foreach} by \code{map} in the expression |
944 above. Scala will still allow \code{map} with side-effect |
939 above. Scala will still allow \code{map} with side-effect |
945 functions, but then reacts with a slightly interesting result. |
940 functions, but then reacts with a slightly interesting result. |
|
941 |
|
942 \subsection*{Aggregates} |
|
943 |
|
944 There is one more usage of for-loops in Java, C/C++ and the like: |
|
945 sometimes you want to \emph{aggregate} something about a list, for |
|
946 example to sum up all its elements. In this case you cannot use map, |
|
947 because maps \emph{transform} one data collection into another data |
|
948 collection. They cannot be used to generate a single integer |
|
949 representing an aggregate. So how is this done in Scala? Let us |
|
950 suppose you want to sum up all elements from a list. You might |
|
951 be tempted to write something like |
|
952 |
|
953 \begin{lstlisting}[numbers=none] |
|
954 var cnt = 0 |
|
955 for (n <- (1 to 8).toList) { |
|
956 cnt += n |
|
957 } |
|
958 print(cnt) |
|
959 \end{lstlisting} |
|
960 |
|
961 \noindent |
|
962 and indeed is accepted Scala code and produces the expected result, |
|
963 namely \code{36}, \textbf{BUT} this is imperative style and not |
|
964 permitted. It uses a \code{var} and therefore violates the immutability |
|
965 property I ask for in your code. |
|
966 |
|
967 So how to do that same thing without using a \code{var}? Well there are |
|
968 several ways. One way is to define the following recursive |
|
969 \code{sum}-function: |
|
970 |
|
971 \begin{lstlisting}[numbers=none] |
|
972 def sum(xs: List[Int]) : Int = |
|
973 if (xs.isEmpty) 0 else xs.head + sum(xs.tail) |
|
974 \end{lstlisting} |
|
975 |
|
976 \noindent |
|
977 You can then call \code{sum((1 to 8).toList)} and obtain the same result |
|
978 without a mutable for-loop. Obviously for simple things like sum, you |
|
979 could have written \code{xs.sum} in the first place. But not all |
|
980 aggregate functions are pre-defined and often you have to write your own |
|
981 recursive function for this. |
|
982 |
946 |
983 |
947 \subsection*{Higher-Order Functions} |
984 \subsection*{Higher-Order Functions} |
948 |
985 |
949 \subsection*{Types} |
986 \subsection*{Types} |
950 |
987 |