├── .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 | 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 | 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 | 115 | --------------------------------------------------------------------------------