├── .idea
├── .name
├── vcs.xml
├── scala_compiler.xml
├── misc.xml
├── hydra.xml
├── modules.xml
├── sbt.xml
└── modules
│ ├── scala-at-light-speed.iml
│ └── scala-at-light-speed-build.iml
├── project
└── build.properties
├── src
└── main
│ └── scala
│ └── com
│ └── rockthejvm
│ ├── Playground.scala
│ ├── PatternMatching.scala
│ ├── Basics.scala
│ ├── ContextualAbstractions.scala
│ ├── Advanced.scala
│ ├── FunctionalProgramming.scala
│ └── ObjectOrientation.scala
├── README.md
└── .gitignore
/.idea/.name:
--------------------------------------------------------------------------------
1 | scala-at-light-speed
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version = 1.3.4
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/scala_compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/hydra.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/Playground.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | /**
4 | * This simple application is an invitation to you to play around with any Scala code you like!
5 | * (not that you'd not be able to create your own application, mind you.)
6 | *
7 | * So get creative - test the code that we write in the videos and try new things!
8 | *
9 | * Daniel @ Rock the JVM
10 | */
11 | object Playground extends App {
12 | println("I love Scala!")
13 | }
14 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/sbt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/PatternMatching.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | object PatternMatching extends App {
4 |
5 | // switch expression
6 | val anInteger = 55
7 | val order = anInteger match {
8 | case 1 => "first"
9 | case 2 => "second"
10 | case 3 => "third"
11 | case _ => anInteger + "th"
12 | }
13 | // PM is an EXPRESSION
14 |
15 | // Case class decomposition
16 | case class Person(name: String, age: Int)
17 | val bob = Person("Bob", 43) // Person.apply("Bob", 43)
18 |
19 | val personGreeting = bob match {
20 | case Person(n, a) => s"Hi, my name is $n and I am $a years old."
21 | case _ => "Something else"
22 | }
23 |
24 | // deconstructing tuples
25 | val aTuple = ("Bon Jovi", "Rock")
26 | val bandDescription = aTuple match {
27 | case (band, genre) => s"$band belongs to the genre $genre"
28 | case _ => "I don't know what you're talking about"
29 | }
30 |
31 | // decomposing lists
32 | val aList = List(1,2,3)
33 | val listDescription = aList match {
34 | case List(_, 2, _) => "List containing 2 on its second position"
35 | case _ => "unknown list"
36 | }
37 |
38 | // if PM doesn't match anything, it will throw a MatchError
39 | // PM will try all cases in sequence
40 | }
41 |
--------------------------------------------------------------------------------
/.idea/modules/scala-at-light-speed.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The official repository for the Rock the JVM Scala at Light Speed course
2 |
3 | This repository contains the code we wrote during [Rock the JVM's Scala at Light Speed](https://rockthejvm.com/course/scala-at-light-speed) mini-course/video series. Unless explicitly mentioned, the code in this repository is exactly what was caught on camera.
4 |
5 | ## How to install
6 |
7 | - if you don't have IntelliJ IDEA installed, install it from the [official site](https://jetbrains.com)
8 | - either clone the repo or download as zip
9 | - open with IntelliJ as an SBT project
10 |
11 | ### How to start
12 |
13 | Clone this repository and checkout the `start` tag by running the following in the repo folder:
14 |
15 | ```
16 | git checkout start
17 | ```
18 |
19 | ### How to see the final code
20 |
21 | The master branch contains the final code, so you can download the repository as is, or if you've navigated somewhere in the code history, then do
22 |
23 | ```
24 | git checkout master
25 | ```
26 |
27 | ### How to run an intermediate state
28 |
29 | The repository was built while recording the videos. Prior to each video, I tagged each commit so you can easily go back to an earlier state of the repo!
30 |
31 | The tags are as follows:
32 |
33 | * `start`
34 | * `basics`
35 | * `object-orientation`
36 | * `functional-programming`
37 | * `pattern-matching`
38 | * `advanced`
39 |
40 | When you watch a video, you can `git checkout` the appropriate tag and the repo will go back to the exact code I had when I started the lecture.
41 |
42 | ### For questions or suggestions
43 |
44 | If you have changes to suggest to this repo, either
45 | - submit a GitHub issue
46 | - tell me in the comments to the videos
47 | - submit a pull request!
48 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/Basics.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | object Basics extends App {
4 |
5 | // defining a value
6 | val meaningOfLife: Int = 42 // const int meaningOfLife = 42;
7 |
8 | // Int, Boolean, Char, Double, Float, String
9 | val aBoolean = false // type is optional
10 |
11 | // strings and string operations
12 | val aString = "I love Scala"
13 | val aComposedString = "I" + " " + "love" + " " + "Scala"
14 | val anInterpolatedString = s"The meaning of life is $meaningOfLife"
15 |
16 | // expressions = structures that can be reduced to a value
17 | val anExpression = 2 + 3
18 |
19 | // if-expression
20 | val ifExpression = if (meaningOfLife > 43) 56 else 999 // in other languages: meaningOfLife > 43 ? 56 : 999
21 | val chainedIfExpression =
22 | if (meaningOfLife > 43) 56
23 | else if (meaningOfLife < 0) -2
24 | else if (meaningOfLife > 999) 78
25 | else 0
26 |
27 | // code blocks
28 | val aCodeBlock = {
29 | // definitions
30 | val aLocalValue = 67
31 |
32 | // value of block is the value of the last expression
33 | aLocalValue + 3
34 | }
35 |
36 | // define a function
37 | def myFunction(x: Int, y: String): String = {
38 | y + " " + x
39 | }
40 |
41 | // recursive functions
42 | def factorial(n: Int): Int =
43 | if (n <= 1) 1
44 | else n * factorial(n - 1)
45 |
46 | /*
47 | factorial(5) = 5 * factorial(4) = 5 * 24 = 120
48 | factorial(4) = 4 * factorial(3) = 4 * 6
49 | factorial(3) = 3 * factorial(2) = 3 * 2
50 | factorial(2) = 2 * factorial(1) = 2 * 1
51 | factorial(1) = 1
52 | */
53 |
54 | // In Scala we don't use loops or iteration, we use RECURSION!
55 |
56 | // the Unit type = no meaningful value === "void" in other languages
57 | // type of SIDE EFFECTS
58 | println("I love Scala") // System.out.println, printf, print, console.log
59 |
60 | def myUnitReturningFunction(): Unit = {
61 | println("I don't love returning Unit")
62 | }
63 |
64 |
65 | val theUnit = ()
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/ContextualAbstractions.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | object ContextualAbstractions {
4 |
5 | // TODO update to Scala 3
6 |
7 | // /*
8 | // 1 - context parameters/arguments
9 | // */
10 | // val aList = List(2,1,3,4)
11 | // val anOrderedList = aList.sorted // contextual argument: (descendingOrdering)
12 | //
13 | // // Ordering
14 | // given descendingOrdering: Ordering[Int] = Ordering.fromLessThan(_ > _) // (a,b) => a > b
15 | //
16 | // // analogous to an implicit val
17 | //
18 | // trait Combinator[A] {
19 | // def combine(x: A, y: A): A
20 | // }
21 | //
22 | // def combineAll[A](list: List[A])(using combinator: Combinator[A]): A =
23 | // list.reduce((a,b) => combinator.combine(a,b))
24 | //
25 | // given intCombinator: Combinator[Int] = new Combinator[Int] {
26 | // override def combine(x: Int, y: Int) = x + y
27 | // }
28 | // val theSum = combineAll(aList) // (intCombinator)
29 | //
30 | // /*
31 | // Given places
32 | // - local scope
33 | // - imported scope
34 | // - the companions of all the types involved in the call
35 | // - companion of List
36 | // - the companion of Int
37 | // */
38 | //
39 | // // context bounds
40 | // def combineAll_v2[A](list: List[A])(using Combinator[A]): A = ???
41 | // def combineAll_v3[A : Combinator](list: List[A]): A = ???
42 | //
43 | // /*
44 | // where context args are useful
45 | // - type classes
46 | // - dependency injection
47 | // - context-dependent functionality
48 | // - type-level programming
49 | // */
50 | //
51 | // /*
52 | // 2 - extension methods
53 | // */
54 | //
55 | // case class Person(name: String) {
56 | // def greet(): String = s"Hi, my name is $name, I love Scala!"
57 | // }
58 | //
59 | // extension (string: String)
60 | // def greet(): String = new Person(string).greet()
61 | //
62 | // val danielsGreeting = "Daniel".greet() // "type enrichment"
63 | //
64 | // // POWER
65 | // extension [A] (list: List[A])
66 | // def combineAllValues(using combinator: Combinator[A]): A =
67 | // list.reduce(combinator.combine)
68 | //
69 | // val theSum_v2 = aList.combineAllValues
70 | //
71 | // def main(args: Array[String]): Unit = {
72 | // println(anOrderedList)
73 | // println(theSum)
74 | // println(theSum_v2)
75 | // }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/Advanced.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | import scala.concurrent.Future
4 | import scala.util.{Failure, Success, Try}
5 | import scala.concurrent.ExecutionContext.Implicits.global
6 |
7 | object Advanced extends App {
8 |
9 | /**
10 | lazy evaluation
11 | */
12 | lazy val aLazyValue = 2
13 | lazy val lazyValueWithSideEffect = {
14 | println("I am so very lazy!")
15 | 43
16 | }
17 |
18 | val eagerValue = lazyValueWithSideEffect + 1
19 | // useful in infinite collections
20 |
21 | /**
22 | "pseudo-collections": Option, Try
23 | */
24 | def methodWhichCanReturnNull(): String = "hello, Scala"
25 | val anOption = Option(methodWhichCanReturnNull()) // Some("hello, Scala")
26 | // option = "collection" which contains at most one element: Some(value) or None
27 |
28 | val stringProcessing = anOption match {
29 | case Some(string) => s"I have obtained a valid string: $string"
30 | case None => "I obtained nothing"
31 | }
32 |
33 | def methodWhichCanThrowException(): String = throw new RuntimeException
34 | val aTry = Try(methodWhichCanThrowException())
35 | // a try = "collection" with either a value if the code went well, or an exception if the code threw one
36 |
37 | val anotherStringProcessing = aTry match {
38 | case Success(validValue) => s"I have obtained a valid string: $validValue"
39 | case Failure(ex) => s"I have obtained an exception: $ex"
40 | }
41 | // map, flatMap, filter
42 |
43 |
44 | /**
45 | * Evaluate something on another thread
46 | * (asynchronous programming)
47 | */
48 | val aFuture = Future {
49 | println("Loading...")
50 | Thread.sleep(1000)
51 | println("I have computed a value.")
52 | 67
53 | }
54 |
55 | // future is a "collection" which contains a value when it's evaluated
56 | // future is composable with map, flatMap and filter
57 |
58 | /**
59 | * Implicits basics
60 | */
61 | // #1: implicit arguments
62 | def aMethodWithImplicitArgs(implicit arg: Int) = arg + 1
63 | implicit val myImplicitInt = 46
64 | println(aMethodWithImplicitArgs) // aMethodWithImplicitArgs(myImplicitInt)
65 |
66 | // #2: implicit conversions
67 | implicit class MyRichInteger(n: Int) {
68 | def isEven() = n % 2 == 0
69 | }
70 |
71 | println(23.isEven()) // new MyRichInteger(23).isEven()
72 | // use this carefully
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/sbt,java,scala,intellij
3 | # Edit at https://www.gitignore.io/?templates=sbt,java,scala,intellij
4 |
5 | ### Intellij ###
6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
8 |
9 | # User-specific stuff
10 | .idea/**/workspace.xml
11 | .idea/**/tasks.xml
12 | .idea/**/usage.statistics.xml
13 | .idea/**/dictionaries
14 | .idea/**/shelf
15 |
16 | # Generated files
17 | .idea/**/contentModel.xml
18 |
19 | # Sensitive or high-churn files
20 | .idea/**/dataSources/
21 | .idea/**/dataSources.ids
22 | .idea/**/dataSources.local.xml
23 | .idea/**/sqlDataSources.xml
24 | .idea/**/dynamic.xml
25 | .idea/**/uiDesigner.xml
26 | .idea/**/dbnavigator.xml
27 |
28 | # Gradle
29 | .idea/**/gradle.xml
30 | .idea/**/libraries
31 |
32 | # Gradle and Maven with auto-import
33 | # When using Gradle or Maven with auto-import, you should exclude module files,
34 | # since they will be recreated, and may cause churn. Uncomment if using
35 | # auto-import.
36 | # .idea/modules.xml
37 | # .idea/*.iml
38 | # .idea/modules
39 | # *.iml
40 | # *.ipr
41 |
42 | # CMake
43 | cmake-build-*/
44 |
45 | # Mongo Explorer plugin
46 | .idea/**/mongoSettings.xml
47 |
48 | # File-based project format
49 | *.iws
50 |
51 | # IntelliJ
52 | out/
53 |
54 | # mpeltonen/sbt-idea plugin
55 | .idea_modules/
56 |
57 | # JIRA plugin
58 | atlassian-ide-plugin.xml
59 |
60 | # Cursive Clojure plugin
61 | .idea/replstate.xml
62 |
63 | # Crashlytics plugin (for Android Studio and IntelliJ)
64 | com_crashlytics_export_strings.xml
65 | crashlytics.properties
66 | crashlytics-build.properties
67 | fabric.properties
68 |
69 | # Editor-based Rest Client
70 | .idea/httpRequests
71 |
72 | # Android studio 3.1+ serialized cache file
73 | .idea/caches/build_file_checksums.ser
74 |
75 | ### Intellij Patch ###
76 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
77 |
78 | # *.iml
79 | # modules.xml
80 | # .idea/misc.xml
81 | # *.ipr
82 |
83 | # Sonarlint plugin
84 | .idea/**/sonarlint/
85 |
86 | # SonarQube Plugin
87 | .idea/**/sonarIssues.xml
88 |
89 | # Markdown Navigator plugin
90 | .idea/**/markdown-navigator.xml
91 | .idea/**/markdown-navigator/
92 |
93 | ### Java ###
94 | # Compiled class file
95 | *.class
96 |
97 | # Log file
98 | *.log
99 |
100 | # BlueJ files
101 | *.ctxt
102 |
103 | # Mobile Tools for Java (J2ME)
104 | .mtj.tmp/
105 |
106 | # Package Files #
107 | *.jar
108 | *.war
109 | *.nar
110 | *.ear
111 | *.zip
112 | *.tar.gz
113 | *.rar
114 |
115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
116 | hs_err_pid*
117 |
118 | ### SBT ###
119 | # Simple Build Tool
120 | # http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
121 |
122 | dist/*
123 | target/
124 | lib_managed/
125 | src_managed/
126 | project/boot/
127 | project/plugins/project/
128 | .history
129 | .cache
130 | .lib/
131 |
132 | ### Scala ###
133 |
134 | # End of https://www.gitignore.io/api/sbt,java,scala,intellij
135 |
136 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/FunctionalProgramming.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | object FunctionalProgramming extends App {
4 |
5 | // Scala is OO
6 | class Person(name: String) {
7 | def apply(age: Int) = println(s"I have aged $age years")
8 | }
9 |
10 | val bob = new Person("Bob")
11 | bob.apply(43)
12 | bob(43) // INVOKING bob as a function === bob.apply(43)
13 |
14 | /*
15 | Scala runs on the JVM
16 | Functional programming:
17 | - compose functions
18 | - pass functions as args
19 | - return functions as results
20 |
21 | Conclusion: FunctionX = Function1, Function2, ... Function22
22 | */
23 |
24 | val simpleIncrementer = new Function1[Int, Int] {
25 | override def apply(arg: Int): Int = arg + 1
26 | }
27 |
28 | simpleIncrementer.apply(23) // 24
29 | simpleIncrementer(23) // simpleIncrementer.apply(23)
30 | // defined a function!
31 |
32 | // ALL SCALA FUNCTIONS ARE INSTANCES OF THESE FUNCTION_X TYPES
33 |
34 | // function with 2 arguments and a String return type
35 | val stringConcatenator = new Function2[String, String, String] {
36 | override def apply(arg1: String, arg2: String): String = arg1 + arg2
37 | }
38 |
39 | stringConcatenator("I love", " Scala") // "I love Scala"
40 |
41 | // syntax sugars
42 | val doubler: Int => Int = (x: Int) => 2 * x
43 | doubler(4) // 8
44 |
45 | /*
46 | equivalent to the much longer:
47 |
48 | val doubler: Function1[Int, Int] = new Function1[Int, Int] {
49 | override def apply(x: Int) = 2 * x
50 | }
51 | */
52 |
53 | // higher-order functions: take functions as args/return functions as results
54 | val aMappedList: List[Int] = List(1,2,3).map(x => x + 1) // HOF
55 | val aFlatMappedList = List(1,2,3).flatMap { x =>
56 | List(x, 2 * x)
57 | } // alternative syntax, same as .flatMap(x => List(x, 2 * x))
58 | val aFilteredList = List(1,2,3,4,5).filter(_ <= 3) // equivalent to x => x <= 3
59 |
60 | // all pairs between the numbers 1, 2, 3 and the letters 'a', 'b', 'c'
61 | val allPairs = List(1,2,3).flatMap(number => List('a', 'b', 'c').map(letter => s"$number-$letter"))
62 |
63 | // for comprehensions
64 | val alternativePairs = for {
65 | number <- List(1,2,3)
66 | letter <- List('a', 'b', 'c')
67 | } yield s"$number-$letter"
68 | // equivalent to the map/flatMap chain above
69 |
70 | /**
71 | * Collections
72 | */
73 |
74 | // lists
75 | val aList = List(1,2,3,4,5)
76 | val firstElement = aList.head
77 | val rest = aList.tail
78 | val aPrependedList = 0 :: aList // List(0,1,2,3,4,5)
79 | val anExtendedList = 0 +: aList :+ 6 // List(0,1,2,3,4,5,6)
80 |
81 | // sequences
82 | val aSequence: Seq[Int] = Seq(1,2,3) // Seq.apply(1,2,3)
83 | val accessedElement = aSequence(1) // the element at index 1: 2
84 |
85 | // vectors: fast Seq implementation
86 | val aVector = Vector(1,2,3,4,5)
87 |
88 | // sets = no duplicates
89 | val aSet = Set(1,2,3,4,1,2,3) // Set(1,2,3,4)
90 | val setHas5 = aSet.contains(5) // false
91 | val anAddedSet = aSet + 5 // Set(1,2,3,4,5)
92 | val aRemovedSet = aSet - 3 // Set(1,2,4)
93 |
94 | // ranges
95 | val aRange = 1 to 1000
96 | val twoByTwo = aRange.map(x => 2 * x).toList // List(2,4,6,8..., 2000)
97 |
98 | // tuples = groups of values under the same value
99 | val aTuple = ("Bon Jovi", "Rock", 1982)
100 |
101 | // maps
102 | val aPhonebook: Map[String, Int] = Map(
103 | ("Daniel", 6437812),
104 | "Jane" -> 327285 // ("Jane", 327285)
105 | )
106 |
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/scala/com/rockthejvm/ObjectOrientation.scala:
--------------------------------------------------------------------------------
1 | package com.rockthejvm
2 |
3 | object ObjectOrientation extends App {
4 |
5 | // java equivalent: public static void main(String[] args)
6 |
7 | // class and instance
8 | class Animal {
9 | // define fields
10 | val age: Int = 0
11 | // define methods
12 | def eat() = println("I'm eating")
13 | }
14 |
15 | val anAnimal = new Animal
16 |
17 | // inheritance
18 | class Dog(val name: String) extends Animal // constructor definition
19 | val aDog = new Dog("Lassie")
20 |
21 | // constructor arguments are NOT fields: need to put a val before the constructor argument
22 | aDog.name
23 |
24 | // subtype polymorphism
25 | val aDeclaredAnimal: Animal = new Dog("Hachi")
26 | aDeclaredAnimal.eat() // the most derived method will be called at runtime
27 |
28 | // abstract class
29 | abstract class WalkingAnimal {
30 | val hasLegs = true // by default public, can restrict by adding protected or private
31 | def walk(): Unit
32 | }
33 |
34 | // "interface" = ultimate abstract type
35 | trait Carnivore {
36 | def eat(animal: Animal): Unit
37 | }
38 |
39 | trait Philosopher {
40 | def ?!(thought: String): Unit // valid method name
41 | }
42 |
43 | // single-class inheritance, multi-trait "mixing"
44 | class Crocodile extends Animal with Carnivore with Philosopher {
45 | override def eat(animal: Animal): Unit = println("I am eating you, animal!")
46 |
47 | override def ?!(thought: String): Unit = println(s"I was thinking: $thought")
48 | }
49 |
50 | val aCroc = new Crocodile
51 | aCroc.eat(aDog)
52 | aCroc eat aDog // infix notation = object method argument, only available for methods with ONE argument
53 | aCroc ?! "What if we could fly?"
54 |
55 | // operators in Scala are actually methods
56 | val basicMath = 1 + 2
57 | val anotherBasicMath = 1.+(2) // equivalent
58 |
59 | // anonymous classes
60 | val dinosaur = new Carnivore {
61 | override def eat(animal: Animal): Unit = println("I am a dinosaur so I can eat pretty much anything")
62 | }
63 |
64 | /*
65 | What you tell the compiler:
66 |
67 | class Carnivore_Anonymous_35728 extends Carnivore {
68 | override def eat(animal: Animal): Unit = println("I am a dinosaur so I can eat pretty much anything")
69 | }
70 |
71 | val dinosaur = new Carnivore_Anonymous_35728
72 | */
73 |
74 | // singleton object
75 | object MySingleton { // the only instance of the MySingleton type
76 | val mySpecialValue = 53278
77 | def mySpecialMethod(): Int = 5327
78 | def apply(x: Int): Int = x + 1
79 | }
80 |
81 | MySingleton.mySpecialMethod()
82 | MySingleton.apply(65)
83 | MySingleton(65) // equivalent to MySingleton.apply(65)
84 |
85 | object Animal { // companions - companion object
86 | // companions can access each other's private fields/methods
87 | // singleton Animal and instances of Animal are different things
88 | val canLiveIndefinitely = false
89 | }
90 |
91 | val animalsCanLiveForever = Animal.canLiveIndefinitely // "static" fields/methods
92 |
93 | /*
94 | case classes = lightweight data structures with some boilerplate
95 | - sensible equals and hash code
96 | - serialization
97 | - companion with apply
98 | - pattern matching
99 | */
100 | case class Person(name: String, age: Int)
101 | // may be constructed without new
102 | val bob = Person("Bob", 54) // Person.apply("Bob", 54)
103 |
104 | // exceptions
105 | try {
106 | // code that can throw
107 | val x: String = null
108 | x.length
109 | } catch { // in Java: catch(Exception e) {...}
110 | case e: Exception => "some faulty error message"
111 | } finally {
112 | // execute some code no matter what
113 | }
114 |
115 | // generics
116 | abstract class MyList[T] {
117 | def head: T
118 | def tail: MyList[T]
119 | }
120 |
121 | // using a generic with a concrete type
122 | val aList: List[Int] = List(1,2,3) // List.apply(1,2,3)
123 | val first = aList.head // int
124 | val rest = aList.tail
125 | val aStringList = List("hello", "Scala")
126 | val firstString = aStringList.head // string
127 |
128 | // Point #1: in Scala we usually operate with IMMUTABLE values/objects
129 | // Any modification to an object must return ANOTHER object
130 | /*
131 | Benefits:
132 | 1) works miracles in multithreaded/distributed env
133 | 2) helps making sense of the code ("reasoning about")
134 | */
135 | val reversedList = aList.reverse // returns a NEW list
136 |
137 | // Point #2: Scala is closest to the OO ideal
138 |
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/.idea/modules/scala-at-light-speed-build.iml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------