Scala - the scalable language
1/////////////////////////////////////////////////
2// 0. Basics
3/////////////////////////////////////////////////
4/*
5 Setup Scala:
6
7 1) Download Scala - http://www.scala-lang.org/downloads
8 2) Unzip/untar to your favorite location and put the bin subdir in your `PATH` environment variable
9*/
10
11/*
12 Try the REPL
13
14 Scala has a tool called the REPL (Read-Eval-Print Loop) that is analogous to
15 commandline interpreters in many other languages. You may type any Scala
16 expression, and the result will be evaluated and printed.
17
18 The REPL is a very handy tool to test and verify code. Use it as you read
19 this tutorial to quickly explore concepts on your own.
20*/
21
22// Start a Scala REPL by running `scala`. You should see the prompt:
23$ scala
24scala>
25
26// By default each expression you type is saved as a new numbered value
27scala> 2 + 2
28res0: Int = 4
29
30// Default values can be reused. Note the value type displayed in the result..
31scala> res0 + 2
32res1: Int = 6
33
34// Scala is a strongly typed language. You can use the REPL to check the type
35// without evaluating an expression.
36scala> :type (true, 2.0)
37(Boolean, Double)
38
39// REPL sessions can be saved
40scala> :save /sites/repl-test.scala
41
42// Files can be loaded into the REPL
43scala> :load /sites/repl-test.scala
44Loading /sites/repl-test.scala...
45res2: Int = 4
46res3: Int = 6
47
48// You can search your recent history
49scala> :h?
501 2 + 2
512 res0 + 2
523 :save /sites/repl-test.scala
534 :load /sites/repl-test.scala
545 :h?
55
56// Now that you know how to play, let's learn a little scala...
57
58/////////////////////////////////////////////////
59// 1. Basics
60/////////////////////////////////////////////////
61
62// Single-line comments start with two forward slashes
63
64/*
65 Multi-line comments, as you can already see from above, look like this.
66*/
67
68// Printing, and forcing a new line on the next print
69println("Hello world!")
70println(10)
71// Hello world!
72// 10
73
74// Printing, without forcing a new line on next print
75print("Hello world")
76print(10)
77// Hello world10
78
79// Declaring values is done using either var or val.
80// val declarations are immutable, whereas vars are mutable. Immutability is
81// a good thing.
82val x = 10 // x is now 10
83x = 20 // error: reassignment to val
84var y = 10
85y = 20 // y is now 20
86
87/*
88 Scala is a statically typed language, yet note that in the above declarations,
89 we did not specify a type. This is due to a language feature called type
90 inference. In most cases, Scala compiler can guess what the type of a variable
91 is, so you don't have to type it every time. We can explicitly declare the
92 type of a variable like so:
93*/
94val z: Int = 10
95val a: Double = 1.0
96
97// Notice automatic conversion from Int to Double, result is 10.0, not 10
98val b: Double = 10
99
100// Boolean values
101true
102false
103
104// Boolean operations
105!true // false
106!false // true
107true == false // false
10810 > 5 // true
109
110// Math is as per usual
1111 + 1 // 2
1122 - 1 // 1
1135 * 3 // 15
1146 / 2 // 3
1156 / 4 // 1
1166.0 / 4 // 1.5
1176 / 4.0 // 1.5
118
119
120// Evaluating an expression in the REPL gives you the type and value of the result
121
1221 + 7
123
124/* The above line results in:
125
126 scala> 1 + 7
127 res29: Int = 8
128
129 This means the result of evaluating 1 + 7 is an object of type Int with a
130 value of 8
131
132 Note that "res29" is a sequentially generated variable name to store the
133 results of the expressions you typed, your output may differ.
134*/
135
136"Scala strings are surrounded by double quotes"
137'a' // A Scala Char
138// 'Single quote strings don't exist' <= This causes an error
139
140// Strings have the usual Java methods defined on them
141"hello world".length
142"hello world".substring(2, 6)
143"hello world".replace("C", "3")
144
145// They also have some extra Scala methods. See also: scala.collection.immutable.StringOps
146"hello world".take(5)
147"hello world".drop(5)
148
149// String interpolation: notice the prefix "s"
150val n = 45
151s"We have $n apples" // => "We have 45 apples"
152
153// Expressions inside interpolated strings are also possible
154val a = Array(11, 9, 6)
155s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old."
156s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples."
157s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"
158
159// Formatting with interpolated strings with the prefix "f"
160f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
161f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"
162
163// Raw strings, ignoring special characters.
164raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r."
165
166// Some characters need to be "escaped", e.g. a double quote inside a string:
167"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown""
168
169// Triple double-quotes let strings span multiple rows and contain quotes
170val html = """<form id="daform">
171 <p>Press belo', Joe</p>
172 <input type="submit">
173 </form>"""
174
175
176/////////////////////////////////////////////////
177// 2. Functions
178/////////////////////////////////////////////////
179
180// Functions are defined like so:
181//
182// def functionName(args...): ReturnType = { body... }
183//
184// If you come from more traditional languages, notice the omission of the
185// return keyword. In Scala, the last expression in the function block is the
186// return value.
187def sumOfSquares(x: Int, y: Int): Int = {
188 val x2 = x * x
189 val y2 = y * y
190 x2 + y2
191}
192
193// The { } can be omitted if the function body is a single expression:
194def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y
195
196// Syntax for calling functions is familiar:
197sumOfSquares(3, 4) // => 25
198
199// You can use parameters names to specify them in different order
200def subtract(x: Int, y: Int): Int = x - y
201
202subtract(10, 3) // => 7
203subtract(y=10, x=3) // => -7
204
205// In most cases (with recursive functions the most notable exception), function
206// return type can be omitted, and the same type inference we saw with variables
207// will work with function return values:
208def sq(x: Int) = x * x // Compiler can guess return type is Int
209
210// Functions can have default parameters:
211def addWithDefault(x: Int, y: Int = 5) = x + y
212addWithDefault(1, 2) // => 3
213addWithDefault(1) // => 6
214
215
216// Anonymous functions look like this:
217(x: Int) => x * x
218
219// Unlike defs, even the input type of anonymous functions can be omitted if the
220// context makes it clear. Notice the type "Int => Int" which means a function
221// that takes Int and returns Int.
222val sq: Int => Int = x => x * x
223
224// Anonymous functions can be called as usual:
225sq(10) // => 100
226
227// If each argument in your anonymous function is
228// used only once, Scala gives you an even shorter way to define them. These
229// anonymous functions turn out to be extremely common, as will be obvious in
230// the data structure section.
231val addOne: Int => Int = _ + 1
232val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)
233
234addOne(5) // => 6
235weirdSum(2, 4) // => 16
236
237
238// The return keyword exists in Scala, but it only returns from the inner-most
239// def that surrounds it.
240// WARNING: Using return in Scala is error-prone and should be avoided.
241// It has no effect on anonymous functions. For example here you may expect foo(7) should return 17 but it returns 7:
242def foo(x: Int): Int = {
243 val anonFunc: Int => Int = { z =>
244 if (z > 5)
245 return z // This line makes z the return value of foo!
246 else
247 z + 2 // This line is the return value of anonFunc
248 }
249 anonFunc(x) + 10 // This line is the return value of foo
250}
251
252foo(7) // => 7
253
254/////////////////////////////////////////////////
255// 3. Flow Control
256/////////////////////////////////////////////////
257
2581 to 5
259val r = 1 to 5
260r.foreach(println)
261
262r foreach println
263// NB: Scala is quite lenient when it comes to dots and brackets - study the
264// rules separately. This helps write DSLs and APIs that read like English
265
266// Why doesn't `println` need any parameters here?
267// Stay tuned for first-class functions in the Functional Programming section below!
268(5 to 1 by -1) foreach (println)
269
270// A while loop
271var i = 0
272while (i < 10) { println("i " + i); i += 1 }
273
274while (i < 10) { println("i " + i); i += 1 } // Yes, again. What happened? Why?
275
276i // Show the value of i. Note that while is a loop in the classical sense -
277 // it executes sequentially while changing the loop variable. while is very
278 // fast, but using the combinators and comprehensions above is easier
279 // to understand and parallelize
280
281// A do-while loop
282i = 0
283do {
284 println("i is still less than 10")
285 i += 1
286} while (i < 10)
287
288// Recursion is the idiomatic way of repeating an action in Scala (as in most
289// other functional languages).
290// Recursive functions need an explicit return type, the compiler can't infer it.
291// Here it's Unit, which is analogous to a `void` return type in Java
292def showNumbersInRange(a: Int, b: Int): Unit = {
293 print(a)
294 if (a < b)
295 showNumbersInRange(a + 1, b)
296}
297showNumbersInRange(1, 14)
298
299
300// Conditionals
301
302val x = 10
303
304if (x == 1) println("yeah")
305if (x == 10) println("yeah")
306if (x == 11) println("yeah")
307if (x == 11) println("yeah") else println("nay")
308
309println(if (x == 10) "yeah" else "nope")
310val text = if (x == 10) "yeah" else "nope"
311
312
313/////////////////////////////////////////////////
314// 4. Data Structures
315/////////////////////////////////////////////////
316
317val a = Array(1, 2, 3, 5, 8, 13)
318a(0) // Int = 1
319a(3) // Int = 5
320a(21) // Throws an exception
321
322val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo")
323m("fork") // java.lang.String = tenedor
324m("spoon") // java.lang.String = cuchara
325m("bottle") // Throws an exception
326
327val safeM = m.withDefaultValue("no lo se")
328safeM("bottle") // java.lang.String = no lo se
329
330val s = Set(1, 3, 7)
331s(0) // Boolean = false
332s(1) // Boolean = true
333
334/* Look up the documentation of map here -
335 * https://www.scala-lang.org/api/current/scala/collection/immutable/Map.html
336 * and make sure you can read it
337 */
338
339
340// Tuples
341
342(1, 2)
343
344(4, 3, 2)
345
346(1, 2, "three")
347
348(a, 2, "three")
349
350// Why have this?
351val divideInts = (x: Int, y: Int) => (x / y, x % y)
352
353// The function divideInts gives you the result and the remainder
354divideInts(10, 3) // (Int, Int) = (3,1)
355
356// To access the elements of a tuple, use _._n where n is the 1-based index of
357// the element
358val d = divideInts(10, 3) // (Int, Int) = (3,1)
359
360d._1 // Int = 3
361d._2 // Int = 1
362
363// Alternatively you can do multiple-variable assignment to tuple, which is more
364// convenient and readable in many cases
365val (div, mod) = divideInts(10, 3)
366
367div // Int = 3
368mod // Int = 1
369
370
371/////////////////////////////////////////////////
372// 5. Object Oriented Programming
373/////////////////////////////////////////////////
374
375/*
376 Aside: Everything we've done so far in this tutorial has been simple
377 expressions (values, functions, etc). These expressions are fine to type into
378 the command-line interpreter for quick tests, but they cannot exist by
379 themselves in a Scala file. For example, you cannot have just "val x = 5" in
380 a Scala file. Instead, the only top-level constructs allowed in Scala are:
381
382 - objects
383 - classes
384 - case classes
385 - traits
386
387 And now we will explain what these are.
388*/
389
390// classes are similar to classes in other languages. Constructor arguments are
391// declared after the class name, and initialization is done in the class body.
392class Dog(br: String) {
393 // Constructor code here
394 var breed: String = br
395
396 // Define a method called bark, returning a String
397 def bark = "Woof, woof!"
398
399 // Values and methods are assumed public. "protected" and "private" keywords
400 // are also available.
401 private def sleep(hours: Int) =
402 println(s"I'm sleeping for $hours hours")
403
404 // Abstract methods are simply methods with no body. If we uncomment the
405 // def line below, class Dog would need to be declared abstract like so:
406 // abstract class Dog(...) { ... }
407 // def chaseAfter(what: String): String
408}
409
410val mydog = new Dog("greyhound")
411println(mydog.breed) // => "greyhound"
412println(mydog.bark) // => "Woof, woof!"
413
414
415// The "object" keyword creates a type AND a singleton instance of it. It is
416// common for Scala classes to have a "companion object", where the per-instance
417// behavior is captured in the classes themselves, but behavior related to all
418// instance of that class go in objects. The difference is similar to class
419// methods vs static methods in other languages. Note that objects and classes
420// can have the same name.
421object Dog {
422 def allKnownBreeds = List("pitbull", "shepherd", "retriever")
423 def createDog(breed: String) = new Dog(breed)
424}
425
426
427// Case classes are classes that have extra functionality built in. A common
428// question for Scala beginners is when to use classes and when to use case
429// classes. The line is quite fuzzy, but in general, classes tend to focus on
430// encapsulation, polymorphism, and behavior. The values in these classes tend
431// to be private, and only methods are exposed. The primary purpose of case
432// classes is to hold immutable data. They often have few methods, and the
433// methods rarely have side-effects.
434case class Person(name: String, phoneNumber: String)
435
436// Create a new instance. Note cases classes don't need "new"
437val george = Person("George", "1234")
438val kate = Person("Kate", "4567")
439
440// With case classes, you get a few perks for free, like getters:
441george.phoneNumber // => "1234"
442
443// Per field equality (no need to override .equals)
444Person("George", "1234") == Person("Kate", "1236") // => false
445
446// Easy way to copy
447// otherGeorge == Person("George", "9876")
448val otherGeorge = george.copy(phoneNumber = "9876")
449
450// And many others. Case classes also get pattern matching for free, see below.
451
452// Traits
453// Similar to Java interfaces, traits define an object type and method
454// signatures. Scala allows partial implementation of those methods.
455// Constructor parameters are not allowed. Traits can inherit from other
456// traits or classes without parameters.
457
458trait Dog {
459 def breed: String
460 def color: String
461 def bark: Boolean = true
462 def bite: Boolean
463}
464class SaintBernard extends Dog {
465 val breed = "Saint Bernard"
466 val color = "brown"
467 def bite = false
468}
469
470scala> val b = new SaintBernard
471res0: SaintBernard = SaintBernard@3e57cd70
472scala> b.breed
473res1: String = Saint Bernard
474scala> b.bark
475res2: Boolean = true
476scala> b.bite
477res3: Boolean = false
478
479// A trait can also be used as Mixin. The class "extends" the first trait,
480// but the keyword "with" can add additional traits.
481
482trait Bark {
483 def bark: String = "Woof"
484}
485trait Dog {
486 def breed: String
487 def color: String
488}
489class SaintBernard extends Dog with Bark {
490 val breed = "Saint Bernard"
491 val color = "brown"
492}
493
494scala> val b = new SaintBernard
495b: SaintBernard = SaintBernard@7b69c6ba
496scala> b.bark
497res0: String = Woof
498
499
500/////////////////////////////////////////////////
501// 6. Pattern Matching
502/////////////////////////////////////////////////
503
504// Pattern matching is a powerful and commonly used feature in Scala. Here's how
505// you pattern match a case class. NB: Unlike other languages, Scala cases do
506// not need breaks, fall-through does not happen.
507
508def matchPerson(person: Person): String = person match {
509 // Then you specify the patterns:
510 case Person("George", number) => "We found George! His number is " + number
511 case Person("Kate", number) => "We found Kate! Her number is " + number
512 case Person(name, number) => "We matched someone : " + name + ", phone : " + number
513}
514
515// Regular expressions are also built in.
516// Create a regex with the `r` method on a string:
517val email = "(.*)@(.*)".r
518
519// Pattern matching might look familiar to the switch statements in the C family
520// of languages, but this is much more powerful. In Scala, you can match much
521// more:
522def matchEverything(obj: Any): String = obj match {
523 // You can match values:
524 case "Hello world" => "Got the string Hello world"
525
526 // You can match by type:
527 case x: Double => "Got a Double: " + x
528
529 // You can specify conditions:
530 case x: Int if x > 10000 => "Got a pretty big number!"
531
532 // You can match case classes as before:
533 case Person(name, number) => s"Got contact info for $name!"
534
535 // You can match regular expressions:
536 case email(name, domain) => s"Got email address $name@$domain"
537
538 // You can match tuples:
539 case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c"
540
541 // You can match data structures:
542 case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"
543
544 // You can nest patterns:
545 case List(List((1, 2, "YAY"))) => "Got a list of list of tuple"
546
547 // Match any case (default) if all previous haven't matched
548 case _ => "Got unknown object"
549}
550
551// In fact, you can pattern match any object with an "unapply" method. This
552// feature is so powerful that Scala lets you define whole functions as
553// patterns:
554val patternFunc: Person => String = {
555 case Person("George", number) => s"George's number: $number"
556 case Person(name, number) => s"Random person's number: $number"
557}
558
559
560/////////////////////////////////////////////////
561// 7. Functional Programming
562/////////////////////////////////////////////////
563
564// Scala allows methods and functions to return, or take as parameters, other
565// functions or methods.
566
567val add10: Int => Int = _ + 10 // A function taking an Int and returning an Int
568List(1, 2, 3) map add10 // List(11, 12, 13) - add10 is applied to each element
569
570// Anonymous functions can be used instead of named functions:
571List(1, 2, 3) map (x => x + 10)
572
573// And the underscore symbol, can be used if there is just one argument to the
574// anonymous function. It gets bound as the variable
575List(1, 2, 3) map (_ + 10)
576
577// If the anonymous block AND the function you are applying both take one
578// argument, you can even omit the underscore
579List("Dom", "Bob", "Natalia") foreach println
580
581
582// Combinators
583// Using `s` from above:
584// val s = Set(1, 3, 7)
585
586s.map(sq)
587
588val sSquared = s.map(sq)
589
590sSquared.filter(_ < 10)
591
592sSquared.reduce (_+_)
593
594// The filter function takes a predicate (a function from A -> Boolean) and
595// selects all elements which satisfy the predicate
596List(1, 2, 3) filter (_ > 2) // List(3)
597case class Person(name: String, age: Int)
598List(
599 Person(name = "Dom", age = 23),
600 Person(name = "Bob", age = 30)
601).filter(_.age > 25) // List(Person("Bob", 30))
602
603
604// Certain collections (such as List) in Scala have a `foreach` method,
605// which takes as an argument a type returning Unit - that is, a void method
606val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100)
607aListOfNumbers foreach (x => println(x))
608aListOfNumbers foreach println
609
610// For comprehensions
611
612for { n <- s } yield sq(n)
613
614val nSquared2 = for { n <- s } yield sq(n)
615
616for { n <- nSquared2 if n < 10 } yield n
617
618for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared
619
620/* NB Those were not for loops. The semantics of a for loop is 'repeat', whereas
621 a for-comprehension defines a relationship between two sets of data. */
622
623
624/////////////////////////////////////////////////
625// 8. Implicits
626/////////////////////////////////////////////////
627
628/* WARNING WARNING: Implicits are a set of powerful features of Scala, and
629 * therefore it is easy to abuse them. Beginners to Scala should resist the
630 * temptation to use them until they understand not only how they work, but also
631 * best practices around them. We only include this section in the tutorial
632 * because they are so commonplace in Scala libraries that it is impossible to
633 * do anything meaningful without using a library that has implicits. This is
634 * meant for you to understand and work with implicits, not declare your own.
635 */
636
637// Any value (vals, functions, objects, etc) can be declared to be implicit by
638// using the, you guessed it, "implicit" keyword. Note we are using the Dog
639// class from section 5 in these examples.
640implicit val myImplicitInt = 100
641implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed)
642
643// By itself, implicit keyword doesn't change the behavior of the value, so
644// above values can be used as usual.
645myImplicitInt + 2 // => 102
646myImplicitFunction("Pitbull").breed // => "Golden Pitbull"
647
648// The difference is that these values are now eligible to be used when another
649// piece of code "needs" an implicit value. One such situation is implicit
650// function arguments:
651def sendGreetings(toWhom: String)(implicit howMany: Int) =
652 s"Hello $toWhom, $howMany blessings to you and yours!"
653
654// If we supply a value for "howMany", the function behaves as usual
655sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!"
656
657// But if we omit the implicit parameter, an implicit value of the same type is
658// used, in this case, "myImplicitInt":
659sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!"
660
661// Implicit function parameters enable us to simulate type classes in other
662// functional languages. It is so often used that it gets its own shorthand. The
663// following two lines mean the same thing:
664// def foo[T](implicit c: C[T]) = ...
665// def foo[T : C] = ...
666
667
668// Another situation in which the compiler looks for an implicit is if you have
669// obj.method(...)
670// but "obj" doesn't have "method" as a method. In this case, if there is an
671// implicit conversion of type A => B, where A is the type of obj, and B has a
672// method called "method", that conversion is applied. So having
673// myImplicitFunction above in scope, we can say:
674"Retriever".breed // => "Golden Retriever"
675"Sheperd".bark // => "Woof, woof!"
676
677// Here the String is first converted to Dog using our function above, and then
678// the appropriate method is called. This is an extremely powerful feature, but
679// again, it is not to be used lightly. In fact, when you defined the implicit
680// function above, your compiler should have given you a warning, that you
681// shouldn't do this unless you really know what you're doing.
682
683
684/////////////////////////////////////////////////
685// 9. Misc
686/////////////////////////////////////////////////
687
688// Importing things
689import scala.collection.immutable.List
690
691// Import all "sub packages"
692import scala.collection.immutable._
693
694// Import multiple classes in one statement
695import scala.collection.immutable.{List, Map}
696
697// Rename an import using '=>'
698import scala.collection.immutable.{List => ImmutableList}
699
700// Import all classes, except some. The following excludes Map and Set:
701import scala.collection.immutable.{Map => _, Set => _, _}
702
703// Java classes can also be imported. Scala syntax can be used
704import java.swing.{JFrame, JWindow}
705
706// Your program's entry point is defined in a scala file using an object, with a
707// single method, main:
708object Application {
709 def main(args: Array[String]): Unit = {
710 // stuff goes here.
711 }
712}
713
714// Files can contain multiple classes and objects. Compile with scalac
715
716
717
718
719// Input and output
720
721// To read a file line by line
722import scala.io.Source
723for(line <- Source.fromFile("myfile.txt").getLines())
724 println(line)
725
726// To write a file use Java's PrintWriter
727val writer = new PrintWriter("myfile.txt")
728writer.write("Writing line for line" + util.Properties.lineSeparator)
729writer.write("Another line here" + util.Properties.lineSeparator)
730writer.close()