The language for this week is Scala, which attempts (among other things) to brings functional programming and a new concurrency model to the JVM.
This was a language I was really keen to know more about. I am using Java a lot, professionally, so I am always looking for options in this ecosystem. I am pretty sure the next book after this one will be a Scala book.
Scala Types
The first thing we learn about Scala is that it is “strongly typed.” This is not a very helpful description, as the definition is fairly loose. And the proof offered by the author that the language is strongly typed is strange:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
So a string cannot be multiplied by a number? By this standard, C is strongly typed as well:
1 2 3 4 5 6 7 8 9 |
|
1 2 3 |
|
As Scala has a theoretical background, perhaps it is useful to move to the language of Type Theory.
A more useful definition than strong typing, is whether a type system is expressive: what do types of expressions tell about how the expressions can be combined, and what to expect when these expressions are evaluated. From this perspective, C types are unexpressive (barely above assembly language), Java’s much better, OCaml, and Haskell better still, and Coq and other dependently-typed languages are perhaps the most expressive of all.
A type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute.
From this perspective, type expressivity is a static (i.e. compile time) feature only. The dynamic equivalent is a type is a tag, i.e. the runtime information about what operations a value supports, so it is impossible to prove any behaviour as impossible before running the program.
Another scale to judge a type system is how verbose it is. In C, as in Java, the type of everything has to be declared. In dynamic languages, no type is needed (or even possible). OCaml and Haskell can figure out the type of most expressions with no need for declarations (which are still useful for documentation). Scala falls somewhere between Java and OCaml. It has type inference over portions of a program.
So when it comes to Scala types (or any type system, really), I have two criteria: whether it is expressive enough to be used to enforce specific properties over portions of a program, and whether it is concise enough that using it does not become a major effort.
Scala syntax
Scala reminds me of OCaml, vaguely. The syntax is fairly concise (especially compared to Java). Scala has list comprehension (as in Python or Haskell), ranges, singletons (object
), and mixins (trait
).
The syntax for the definition of functions (that is, methods that return a value) is somewhat strange, as it requires an equal sign:
1 2 3 |
|
Procedures (methods that return nothing) only need one when they are defined as returning Unit
(which is void
for Scala):
1 2 3 4 5 6 7 |
|
Nothing overly complex, and if I believe the error message (“warning: Detected apparent refinement of Unit; are you missing an ‘=’ sign?”), the reason for this syntax is to support other constructs. Still, I had this error a few times as I wrote my code, before I finally internalized the rule.
The rest of the syntax (as introduced today) is straightforward, and easy to get used to (at least for me).
Exercises
For a first day, the exercise was rather demanding.
Tic-Tac-Toe
My first version is, admittedly, ugly. I build a list of the possible lines (i.e. rows, columns or diagonals) in the board (as a list of pairs of indices) in lines
, then in the function winner
I iterate over this list and check if the positions for each pair have the same content, and if this content belong to a player or not.
For the bonus part, I use print_board
, which displays a board with numbers on unused locations, and play
, which asks players in turn for their move, checks whether the move is valid, whether it is a winning move, and switches between players when needed.
The play
function relies on variables more than I would like, but on the other hand it is harder to model a board with no update at all.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
|
When running it, it will first test the code by playing a predefined game. Then the bonus code is run, and an interactive game can be tried:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
|
The interactive code is not great (see below for an improvement); especially a draw
Tic-Tac-Toe with class
A second version, slightly cleaned up (but presumably still ugly), this time in a class. Only one variable remains (the board); everything else is immutable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
|
It still handles normal victory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
as well as the more common case of draw:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|
Wrapping Up Day 1
Scala seems easy enough to get started with. The syntax is readable; the semantic close enough to Java’s (and other mainstream languages) that there is little surprise.