├── .gitignore ├── .travis.yml ├── README.md ├── Scala_logo.png ├── cheat-sheet.org ├── codecentric.png ├── profile.png ├── scala-cheat-sheet.tex └── shell.nix /.gitignore: -------------------------------------------------------------------------------- 1 | scala-cheat-sheet.* 2 | auto/ 3 | _minted-scala-cheat-sheet/ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: 2 | - nix 3 | 4 | script: 5 | - nix-shell --pure --command "latexmk -shell-escape -pdf scala-cheat-sheet.tex" 6 | - convert -density 300 scala-cheat-sheet.pdf scala-cheat-sheet.png 7 | - convert scala-cheat-sheet*.png -append scala-cheat-sheet.png 8 | 9 | after_success: 10 | - git config --global user.email "travis-ci@travis.org" 11 | - git config --global user.name "Travis CI" 12 | - git remote rm origin 13 | - git remote add origin https://markus1189:$GITHUB_API_KEY@github.com/markus1189/scala-cheat-sheet.git 14 | - git checkout -b pdf 15 | - git add -f scala-cheat-sheet.pdf 16 | - git add -f scala-cheat-sheet.png 17 | - git commit -m "$(date --iso-8601) @ $(git rev-list --max-count=1 --abbrev-commit $TRAVIS_BRANCH)" -m "[skip ci]" 18 | - git push -f origin pdf 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The codecentric Scala Cheat Sheet 2 | [![Build Status](https://travis-ci.org/markus1189/scala-cheat-sheet.svg)](https://travis-ci.org/markus1189/scala-cheat-sheet) 3 | 4 | Download: https://github.com/markus1189/scala-cheat-sheet/raw/pdf/scala-cheat-sheet.pdf 5 | 6 | ### Preview 7 | 8 | ![preview](https://github.com/markus1189/scala-cheat-sheet/raw/pdf/scala-cheat-sheet.png) 9 | -------------------------------------------------------------------------------- /Scala_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markus1189/scala-cheat-sheet/53499de3f494a6d98c032ebc32c242979125339f/Scala_logo.png -------------------------------------------------------------------------------- /cheat-sheet.org: -------------------------------------------------------------------------------- 1 | * Cheat Sheet 2 | ** TODO data types 3 | ** DONE lazy val / val / var 4 | CLOSED: [2017-05-15 Mon 20:32] 5 | ** TODO mutable / immutable collections 6 | - scala.collection.immutable. 7 | - scala.collection.mutable 8 | ** TODO Option 9 | - getOrElse 10 | - orElse 11 | - Option(null) // None 12 | - Some(null) // Some(null) 13 | - None 14 | - Option.empty[Int] 15 | 16 | ** TODO Either 17 | - since 2.12: right biased, swap 18 | - fold/getOrElse/ 19 | - toOption/toTry 20 | 21 | ** TODO Try (scala.util) 22 | - fold 23 | - getOrElse 24 | - orElse 25 | - recover 26 | - transform 27 | 28 | ** TODO Collections methods: 29 | - collect/collectFirst/find 30 | - forall/exists 31 | - map/flatMap/filter 32 | - head/headOption 33 | 34 | ** TODO Futures 35 | - Duration: 2.seconds (import scala.concurrent.durations._) 36 | - Await.result(future, 42.seconds) // Only once in main, avoid! 37 | - 38 | 39 | ** DONE Ranges 40 | CLOSED: [2017-05-15 Mon 20:37] 41 | - 1 to 10 42 | - 1 until 10 43 | - 1.to(10, 2) 44 | 45 | ** TODO Comments 46 | - // and /* */ and /** */ 47 | 48 | ** TODO Pattern Matching 49 | - list of patterns 50 | - examples? 51 | 52 | ** TODO ADTs 53 | - sealed trait + final case classes 54 | 55 | ** TODO REPL 56 | - :t[ype] 57 | - :he[lp] 58 | - :h? 59 | - :imports 60 | - :implicits 61 | - :load 62 | - :paste 63 | - :quit 64 | - :reset 65 | - :kind 66 | ** TODO JSON? 67 | ** TODO case classes 68 | - toString 69 | - unapply 70 | - apply 71 | - serializable 72 | - every param is a val field 73 | ** TODO Upper bounds / lower bounds / ... 74 | - upper: A <: B 75 | - lower: A >: B 76 | - careful: lhs introduces a NEW one 77 | 78 | ** TODO context bounds 79 | - mostly used for type classes 80 | - equivalent to implicit parameter list 81 | 82 | ** TODO implicits 83 | - rules for search 84 | - implicit val / def / class 85 | - implicitly[A] 86 | 87 | ** TODO String fun: 88 | - multiline with/out margin 89 | - raw 90 | - substitute 91 | - custom? 92 | 93 | ** TODO Regex: 94 | - "foo".r 95 | - matching of groups 96 | 97 | ** TODO map / flatMap / (with)Filter, the holy trinity 98 | ** TODO for expression / for loop 99 | ** DONE imports: 100 | CLOSED: [2017-05-15 Mon 21:18] 101 | - import foo.x 102 | - import foo.{x,y} 103 | - import foo.x, bar.y 104 | - import foo._ 105 | - import foo.{Int => FooInt} 106 | - def foo(x: Class) = { import x._ } 107 | - wildcard, renaming, everywhere 108 | 109 | ** TODO typeclasses? 110 | ** TODO package clauses 111 | - almost as in java 112 | - ... but chainable 113 | 114 | ** TODO anyval 115 | - single val and `extends AnyVal` 116 | - rules for allocation? 117 | ** TODO usage of underscores 118 | ** TODO "sealed" modifier 119 | ** TODO constructors via this 120 | ** TODO Modifiers 121 | - private 122 | - object-private 123 | - class-private 124 | - qualified-private 125 | - protected 126 | - object-protected 127 | - override 128 | - abstract override 129 | - abstract 130 | - final 131 | - sealed 132 | - lazy 133 | ** TODO sbt: 134 | - simple build? 135 | - compile / test / test:compile / ~test / etc 136 | 137 | ** TODO implicit evidence: 138 | - <:< 139 | - =:= 140 | ** TODO objects 141 | - singletons, lazy init 142 | - companions 143 | ** TODO type hierarchy 144 | - Any / AnyRef / AnyVal 145 | - Nothing 146 | ** TODO operators and precedence 147 | - (==) is not as in java reference equality! 148 | - the name is important 149 | - the magic colon in the name of defs 150 | - unary operators 151 | ** TODO control structures 152 | - while (...) { ... } 153 | - do { ... } while(...) 154 | - try / catch / finally 155 | ** DONE varargs 156 | CLOSED: [2017-05-16 Tue 21:47] 157 | ** TODO type alias / type members 158 | ** TODO IntelliJ shortcuts 159 | - show implicit parameters 160 | - show implicit conversions 161 | - ... 162 | ** TODO collection performance overview? 163 | ** TODO Early definitions 164 | -------------------------------------------------------------------------------- /codecentric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markus1189/scala-cheat-sheet/53499de3f494a6d98c032ebc32c242979125339f/codecentric.png -------------------------------------------------------------------------------- /profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markus1189/scala-cheat-sheet/53499de3f494a6d98c032ebc32c242979125339f/profile.png -------------------------------------------------------------------------------- /scala-cheat-sheet.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,landscape,a4paper]{article} 2 | \usepackage[T1]{fontenc} 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[ngerman]{babel} 5 | \usepackage{tikz} 6 | \usetikzlibrary{shapes,positioning,arrows,fit,calc,graphs,graphs.standard,trees,arrows.meta} 7 | \usepackage[nosf]{kpfonts} 8 | \usepackage{multicol} 9 | \usepackage{wrapfig} 10 | \usepackage[top=2mm,bottom=13mm,left=2mm,right=2mm]{geometry} 11 | \usepackage[framemethod=tikz]{mdframed} 12 | \usepackage{microtype} 13 | \usepackage{minted} 14 | \usepackage{titlesec} 15 | \usepackage{keystroke} 16 | \usepackage{todonotes} 17 | \usepackage{wrapfig} 18 | \newcommand{\TODO}[2][]{\todo[inline,color=green!40,linecolor=green!50,#1]{\small TODO #2}} 19 | 20 | \renewcommand\familydefault{\sfdefault} 21 | 22 | \definecolor{mygreen}{HTML}{4F8D4F} 23 | \definecolor{myblue}{HTML}{3C6A6A} 24 | \definecolor{myyellow}{HTML}{B18663} 25 | \definecolor{myred}{HTML}{B16363} 26 | \definecolor{sectionbg}{HTML}{D5D5D5} 27 | 28 | \tikzstyle{every node}=[font=\footnotesize\sffamily] 29 | \tikzstyle{sup}=[rectangle,draw,fill=myblue!50,rounded corners=.8ex] 30 | \tikzstyle{sub}=[rectangle,draw,fill=mygreen!70,rounded corners=.8ex] 31 | \tikzstyle{block} = [rectangle, draw, text width=2.5cm, text centered, rounded corners, minimum height=4em,fill=blue!20] 32 | \tikzstyle{line} = [->, draw,thick, >={open triangle 60}] 33 | \tikzstyle{cloud} = [draw, ellipse, text width=2.5cm, text centered] 34 | \tikzstyle{edge from parent}=[<-,thick,draw, >={open triangle 60}] 35 | 36 | \let\bar\overline 37 | 38 | \def\firstcircle{(0,0) circle (1.5cm)} 39 | \def\secondcircle{(0:2cm) circle (1.5cm)} 40 | 41 | \colorlet{circle edge}{myblue} 42 | \colorlet{circle area}{myblue!5} 43 | 44 | \tikzset{filled/.style={fill=circle area, draw=circle edge, thick}, 45 | outline/.style={draw=circle edge, thick}, >={open triangle 60}} 46 | 47 | \pgfdeclarelayer{background} 48 | \pgfsetlayers{background,main} 49 | 50 | \everymath\expandafter{\the\everymath \color{myblue}} 51 | \everydisplay\expandafter{\the\everydisplay \color{myblue}} 52 | 53 | \renewcommand{\baselinestretch}{.8} 54 | \pagestyle{empty} 55 | 56 | \global\mdfdefinestyle{header}{% 57 | linecolor=gray,linewidth=1pt,% 58 | leftmargin=0mm,rightmargin=0mm,skipbelow=0mm,skipabove=0mm, 59 | } 60 | 61 | \newcommand{\header}{ 62 | \vspace{1mm} 63 | \begin{center} 64 | \includegraphics[height=09mm]{codecentric.png} 65 | presents the \begin{minipage}{08mm} 66 | \vspace{-1pt}\includegraphics[height=3mm]{Scala_logo.png} 67 | \end{minipage} 68 | \vspace{0pt} Cheat Sheet, for Scala 2.12 69 | \end{center} 70 | } 71 | 72 | \makeatletter 73 | 74 | \newcommand{\colorsection}[1]{\colorbox{sectionbg}{\parbox{\textwidth-215\fboxsep}{\centering#1}}} 75 | \newcommand{\colorsubsection}[1]{\footnotesize\colorbox{sectionbg}{\parbox{\textwidth-250\fboxsep}{\centering#1}}} 76 | \titleformat{\section}[block]{\color{myblue}\sffamily\small\bfseries\filcenter}{}{1em}{\colorsection} 77 | \titleformat{\subsection}[block]{\color{myblue}\sffamily\small\bfseries\filcenter}{}{1em}{\colorsubsection} 78 | 79 | \def\multi@column@out{% 80 | \ifnum\outputpenalty <-\@M 81 | \speci@ls \else 82 | \ifvoid\colbreak@box\else 83 | \mult@info\@ne{Re-adding forced 84 | break(s) for splitting}% 85 | \setbox\@cclv\vbox{% 86 | \unvbox\colbreak@box 87 | \penalty-\@Mv\unvbox\@cclv}% 88 | \fi 89 | \splittopskip\topskip 90 | \splitmaxdepth\maxdepth 91 | \dimen@\@colroom 92 | \divide\skip\footins\col@number 93 | \ifvoid\footins \else 94 | \leave@mult@footins 95 | \fi 96 | \let\ifshr@kingsaved\ifshr@king 97 | \ifvbox \@kludgeins 98 | \advance \dimen@ -\ht\@kludgeins 99 | \ifdim \wd\@kludgeins>\z@ 100 | \shr@nkingtrue 101 | \fi 102 | \fi 103 | \process@cols\mult@gfirstbox{% 104 | %%%%% START CHANGE 105 | \ifnum\count@=\numexpr\mult@rightbox+2\relax 106 | \setbox\count@\vsplit\@cclv to \dimexpr \dimen@-1cm\relax 107 | \setbox\count@\vbox to \dimen@{\vbox to 1.5cm{\header}\unvbox\count@\vss}% 108 | \else 109 | \setbox\count@\vsplit\@cclv to \dimen@ 110 | \fi 111 | %%%%% END CHANGE 112 | \set@keptmarks 113 | \setbox\count@ 114 | \vbox to\dimen@ 115 | {\unvbox\count@ 116 | \remove@discardable@items 117 | \ifshr@nking\vfill\fi}% 118 | }% 119 | \setbox\mult@rightbox 120 | \vsplit\@cclv to\dimen@ 121 | \set@keptmarks 122 | \setbox\mult@rightbox\vbox to\dimen@ 123 | {\unvbox\mult@rightbox 124 | \remove@discardable@items 125 | \ifshr@nking\vfill\fi}% 126 | \let\ifshr@king\ifshr@kingsaved 127 | \ifvoid\@cclv \else 128 | \unvbox\@cclv 129 | \ifnum\outputpenalty=\@M 130 | \else 131 | \penalty\outputpenalty 132 | \fi 133 | \ifvoid\footins\else 134 | \PackageWarning{multicol}% 135 | {I moved some lines to 136 | the next page.\MessageBreak 137 | Footnotes on page 138 | \thepage\space might be wrong}% 139 | \fi 140 | \ifnum \c@tracingmulticols>\thr@@ 141 | \hrule\allowbreak \fi 142 | \fi 143 | \ifx\@empty\kept@firstmark 144 | \let\firstmark\kept@topmark 145 | \let\botmark\kept@topmark 146 | \else 147 | \let\firstmark\kept@firstmark 148 | \let\botmark\kept@botmark 149 | \fi 150 | \let\topmark\kept@topmark 151 | \mult@info\tw@ 152 | {Use kept top mark:\MessageBreak 153 | \meaning\kept@topmark 154 | \MessageBreak 155 | Use kept first mark:\MessageBreak 156 | \meaning\kept@firstmark 157 | \MessageBreak 158 | Use kept bot mark:\MessageBreak 159 | \meaning\kept@botmark 160 | \MessageBreak 161 | Produce first mark:\MessageBreak 162 | \meaning\firstmark 163 | \MessageBreak 164 | Produce bot mark:\MessageBreak 165 | \meaning\botmark 166 | \@gobbletwo}% 167 | \setbox\@cclv\vbox{\unvbox\partial@page 168 | \page@sofar}% 169 | \@makecol\@outputpage 170 | \global\let\kept@topmark\botmark 171 | \global\let\kept@firstmark\@empty 172 | \global\let\kept@botmark\@empty 173 | \mult@info\tw@ 174 | {(Re)Init top mark:\MessageBreak 175 | \meaning\kept@topmark 176 | \@gobbletwo}% 177 | \global\@colroom\@colht 178 | \global \@mparbottom \z@ 179 | \process@deferreds 180 | \@whilesw\if@fcolmade\fi{\@outputpage 181 | \global\@colroom\@colht 182 | \process@deferreds}% 183 | \mult@info\@ne 184 | {Colroom:\MessageBreak 185 | \the\@colht\space 186 | after float space removed 187 | = \the\@colroom \@gobble}% 188 | \set@mult@vsize \global 189 | \fi} 190 | 191 | \makeatother 192 | \setlength{\parindent}{0pt} 193 | 194 | \mdfsetup{middlelinecolor=myblue, middlelinewidth=1pt, roundcorner=10pt} 195 | 196 | \begin{document} 197 | \setminted{fontsize=\footnotesize} 198 | 199 | \footnotesize 200 | \begin{multicols*}{4} 201 | 202 | \section{Variables \& Methods} 203 | \begin{minted}{scala} 204 | var x = "mutable" 205 | val y = "immutable" 206 | 207 | // Initialized once on first access 208 | lazy val z = "lazy" 209 | 210 | // Pattern matching on left side 211 | val (one, two) = ("one", 2) 212 | 213 | // Simple method 214 | def add(n: Int, m: Int): Int = n + m 215 | 216 | // Curried version (one argument per list) 217 | def add(n: Int)(m: Int): Int = n + m 218 | 219 | // By-name parameters, evaluates `a` twice 220 | def twice[A](a: => A) = { a; a } 221 | 222 | // Repeated Parameters (Varargs) 223 | def many(ns: Int*): Seq[Int] = ns 224 | 225 | // Calling a varargs method with a `Seq` 226 | > many(Seq(1, 2) :_*) 227 | \end{minted} 228 | 229 | \section{Strings} 230 | 231 | \begin{minted}{scala} 232 | val answer: Int = 42 233 | // add `s` prefix for interpolation 234 | s"The answer is: $answer" 235 | 236 | // use ${} for more complex expressions 237 | s"The answer is: ${21 * 2}" 238 | 239 | // """ enclose a multiline string 240 | """ 241 | Inside triple quotes there 242 | is no need to escape: \ 243 | """ 244 | \end{minted} 245 | 246 | \section{Regular Expressions} 247 | 248 | \begin{minted}{scala} 249 | val time = """(\d{1,2}):(\d{2})""".r 250 | 251 | > "16:03" match { case time(_*) => "matched!" } 252 | \end{minted} 253 | \begin{minted}{text} 254 | res: String = matched! 255 | \end{minted} 256 | 257 | \begin{minted}{scala} 258 | // extract matched groups 259 | > "16:12" match { case time(h,m) => 260 | s"Hours: $h, minutes: $m" 261 | } 262 | \end{minted} 263 | \begin{minted}{text} 264 | res: String = Hours: 16, minutes: 12 265 | \end{minted} 266 | 267 | 268 | \section{Classes} 269 | 270 | \begin{minted}{scala} 271 | // Implicit default constructor 272 | // `AnyRef` plays the role of `Object` 273 | class Foo extends AnyRef { 274 | val bar: Int = 42 275 | def foobar: Boolean = true 276 | } 277 | 278 | // Parameterized constructor 279 | class Foo(msg: String) { ... } 280 | 281 | // Additional constructor 282 | class Foo(msg: String) { 283 | def this(n: Int) = this(n.toString) 284 | } 285 | 286 | // Can inherit from exactly one class 287 | class Bar extends Foo("foo") 288 | \end{minted} 289 | 290 | \section{Objects} 291 | 292 | \begin{mdframed} 293 | \footnotesize Objects hold ``\textit{static}'' members. When used 294 | as a companion object, it is relevant during implicit search. Objects 295 | are \textit{singletons}. 296 | \end{mdframed} 297 | 298 | \begin{minted}{scala} 299 | object Foo { 300 | val hello: String = "Hello" 301 | def world: String = "World" 302 | } 303 | 304 | // Companion object: 305 | // class and object share name and source file 306 | class Bar 307 | object Bar { ... } 308 | \end{minted} 309 | 310 | \section{Traits} 311 | 312 | \begin{mdframed} 313 | \footnotesize 314 | The \mintinline{scala}|sealed| modifier forbids extension of the 315 | trait from a different source file than the one it is defined in. 316 | This allows exhaustiveness checks while pattern matching. 317 | \end{mdframed} 318 | 319 | \begin{minted}{scala} 320 | trait Foo { 321 | // can have abstract members 322 | def foo: String 323 | 324 | // can have implementations 325 | def bar: Unit = println("bar") 326 | } 327 | 328 | // Multiple traits can be mixed-in 329 | trait Bar 330 | class Foobar extends Foo with Bar { 331 | override def foo = "foo" 332 | } 333 | \end{minted} 334 | 335 | \section{Case Classes} 336 | 337 | \begin{minted}{scala} 338 | // class definition prefixed with `case` 339 | case class Person(name: String, age: Int) 340 | \end{minted} 341 | 342 | What \mintinline{scala}|case| does: 343 | \begin{enumerate} 344 | \item constructor parameters are promoted to fields 345 | \item generates companion object with \mintinline{scala}|apply| and \mintinline{scala}|unapply| 346 | \item generates the \mintinline{scala}|copy| method 347 | \item generates \mintinline{scala}|equals|, \mintinline{scala}|hashCode| and \mintinline{scala}|toString| 348 | \end{enumerate} 349 | 350 | \section{For-loop and For-comprehension} 351 | 352 | \begin{mdframed} 353 | \footnotesize For-loops: iterate for side-effects only. 354 | For-comprehensions: chain effectful computations. 355 | \end{mdframed} 356 | 357 | \begin{minted}{scala} 358 | // for-loop 359 | for (i <- 1 to 10) println(i) 360 | 361 | // nested for-loop 362 | for (i <- 1 to 10; j <- 1 to 10) println((i, j)) 363 | 364 | // for-comprehension 365 | for (i <- 1 to 3; j <- 1 to i) yield i * y 366 | 367 | // guards in for-loops and for-comprehensions 368 | for (i <- 1 to 5 if i > 4) yield i 369 | 370 | // curly braces for multiline expressions 371 | for { 372 | i <- 1 to 5 373 | j <- 1 to i 374 | if j % 2 == 1 375 | } yield i * j 376 | \end{minted} 377 | \section{Pattern Matching} 378 | 379 | \begin{minted}{scala} 380 | arg match { 381 | // Variable Patterns 382 | case x => 383 | // Typed Patterns 384 | case x: String => 385 | // Literal Patterns 386 | case 42 => 387 | // Stable Identifier Patterns 388 | case `foo` => 389 | // Constructor Patterns 390 | case Foo(x,y) => 391 | // Tuple Patterns 392 | case (x,y,z) => 393 | // Extractor Patterns 394 | // (See 'Custom Extractors') 395 | case NumString(x) => 396 | // Pattern Sequences 397 | case x1 +: x2 +: xs => 398 | // Pattern Alternatives 399 | case true | 42 | "str" => 400 | // Pattern Binders 401 | case pair@(x,y) => 402 | } 403 | \end{minted} 404 | 405 | \section{Custom Extractors} 406 | 407 | \begin{minted}{scala} 408 | // Return Boolean from unapply 409 | object Even { 410 | def unapply(n: Int): Boolean = 411 | n % 2 == 0 412 | } 413 | \end{minted} 414 | 415 | \begin{minted}{text} 416 | > 41 match { case Even() => '!' } 417 | scala.MatchError: 41 ... 418 | > 42 match { case Even() => "even!" } 419 | res: String = "even!" 420 | \end{minted} 421 | 422 | \begin{minted}{scala} 423 | // Return Option from unapply 424 | object NumString { 425 | def unapply(s: String): Option[Int] = 426 | Try(s.toInt).toOption 427 | } 428 | \end{minted} 429 | 430 | \begin{minted}{text} 431 | > "42" match { case NumString(n) => n } 432 | res: Int = 42 433 | > "scala" match { case NumString(n) => n } 434 | scala.MatchError: scala 435 | \end{minted} 436 | 437 | \begin{minted}{scala} 438 | // Alternatively define unapplySeq 439 | object Words { 440 | def unapplySeq(s: String): Option[Seq[String]] = 441 | Some(s.split("\\s+").to[Seq]) 442 | } 443 | \end{minted} 444 | 445 | \begin{minted}{text} 446 | > "foo bar baz" match { case Words(ws) => ws } 447 | res: Seq[String] = Vector("foo", "bar", "baz") 448 | > "test" match { case Words("foo" +: _) => 1 } 449 | scala.MatchError: test 450 | \end{minted} 451 | 452 | \section{Type Parameters} 453 | 454 | \begin{minted}{scala} 455 | // Two type parameters A and B 456 | def foo[A, B](a: A, b: B) = ??? 457 | 458 | // Upper Bound, A has to be a subtype 459 | def foo[A <: String] 460 | 461 | // Lower Bound, A has to be a supertype 462 | def foo[A :> String] 463 | 464 | // Context Bound 465 | def foo[A: Ordering](x: A, y: A): Boolean = { 466 | import Ordering.Implicits._ 467 | x < y 468 | } 469 | // Context Bounds desugar to implicit params 470 | def foo[A](x: A, y: A)( 471 | implicit evidence$1: Ordering[A]): Boolean 472 | \end{minted} 473 | 474 | \section{Variance} 475 | 476 | \begin{center} 477 | \begin{tikzpicture}[auto,grow=right] 478 | \node[sup](a){A}; 479 | \node[sup, xshift=03mm, right of=a ](f-a-inv){F[A]}; 480 | \node[sup, xshift=10mm, right of=f-a-inv](f-a-cov){F[+A]}; 481 | \node[sub, xshift=10mm, right of=f-a-cov](f-a-con){F[-A]}; 482 | 483 | \node[below of=a](l1){}; 484 | \node[xshift=03mm, right of=l1](l2){invariant}; 485 | \node[xshift=10mm, right of=l2](l3){covariant}; 486 | \node[xshift=10mm, right of=l3](l4){contravariant}; 487 | 488 | \node[sub, below of=l1](b){B}; 489 | \node[sup, xshift=03mm, right of=b ](f-b-inv){F[B]}; 490 | \node[sub, xshift=10mm, right of=f-b-inv](f-b-cov){F[+B]}; 491 | \node[sup, xshift=10mm, right of=f-b-cov](f-b-con){F[-B]}; 492 | 493 | \path [line] (b) -- (a); 494 | % no relation for invariance 495 | \path [line, -] (f-b-cov) -- (l3) ; 496 | \path [line] (l3) -- (f-a-cov) ; 497 | \path [line, -] (f-a-con) -- (l4) ; 498 | \path [line] (l4) -- (f-b-con) ; 499 | \end{tikzpicture} 500 | \end{center} 501 | 502 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 503 | % \newpage{} 504 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 505 | 506 | \section{Implicits} 507 | There are two categories of places where Scala searches for implicits: 508 | \begin{enumerate} 509 | \item identifiers accessible \textit{without prefix} at the call-site 510 | \item implicit scope: all companion objects of classes associated 511 | with the implicit's type 512 | \end{enumerate} 513 | 514 | \subsection{The implicit modifier} 515 | 516 | \begin{minted}{scala} 517 | // implicit values 518 | implicit val n: Int = 42 519 | 520 | // implicit conversions 521 | implicit def f(n: Int): String = n.toString 522 | 523 | // implicit classes 524 | implicit class Wrapper[A](val a: A) { 525 | def printMe: Unit = println(a) 526 | } 527 | 528 | // implicit parameters 529 | def foo(implicit ec: ExecutionContext) = ??? 530 | \end{minted} 531 | 532 | \section{Types} 533 | 534 | \begin{center} 535 | \begin{tikzpicture}[auto,grow=right] 536 | \tikzstyle{level 1}=[sibling distance=16em,level distance=3em] 537 | \tikzstyle{level 2}=[sibling distance=4em,level distance=6em] 538 | \node [sup] (any) {Any} 539 | child{node [sup] (anyval) {AnyVal} 540 | child{node [sub] (nums) {Numbers}} 541 | child{node [sub] (char) {Char}} 542 | child{node [sub] (bool) {Boolean}} 543 | child{node [sub,fill=myred!60] (yanyval) {Your AnyVal}} 544 | } 545 | child{node [sup] (anyref) {AnyRef} 546 | child{node [sub] (colls) {Collections}} 547 | child{node [sub,fill=myred!60] (clss) {Your Class}} 548 | child{node [sub] (str) {String}} 549 | }; 550 | \node[sup,xshift=1cm,right of=clss](null){Null}; 551 | \node[sup,xshift=4.5cm,right of=any](nothing){Nothing}; 552 | \node[sup,above of=anyref](obj){Object}; 553 | \path [line] (null) -- (str); 554 | \path [line] (null) -- (colls); 555 | \path [line] (null) -- (clss); 556 | \path [line] (nothing) -- (null); 557 | \path [line] (nothing) -- (bool); 558 | \path [line] (nothing) -- (yanyval); 559 | \path [line] (nothing) -- (char); 560 | \path [line] (nothing) -- (nums); 561 | \path [line,dashed,-] (obj) -- (anyref); 562 | \end{tikzpicture} 563 | \end{center} 564 | 565 | \section{Option} 566 | \begin{mdframed} 567 | \footnotesize 568 | Replaces \texttt{null}, there is only \textit{one} obvious 569 | reason for a missing value. 570 | \end{mdframed} 571 | \begin{center} 572 | \begin{tikzpicture}[ 573 | level 1/.style={sibling distance=10em}] 574 | \node[sup]{Option[A]} 575 | child{node[sub] {None}} 576 | child{node[sub]{Some[A](value: A)}} 577 | ; 578 | \end{tikzpicture} 579 | \end{center} 580 | \begin{minted}{scala} 581 | val some: Option[Int] = Some(1) 582 | val none: Option[Int] = None 583 | 584 | // getOrElse 585 | > some.getOrElse(42) 586 | res: Int = 1 587 | > none.getOrElse(42) 588 | res: Int = 42 589 | 590 | // fold 591 | > some.fold("")(_.toString) 592 | res: String = "1" 593 | > none.fold("")(_.toString) 594 | res: String = "" 595 | 596 | // orElse 597 | > some.orElse(none) 598 | res: Option[Int] = Some(1) 599 | > none.orElse(Some(42)) 600 | res: Option[Int] = Some(42) 601 | 602 | \end{minted} 603 | \section{Either} 604 | \begin{mdframed} 605 | \footnotesize 606 | \textit{Domain} errors that have to be handled, there are 607 | \textit{multiple} reasons for an error. 608 | \end{mdframed} 609 | \begin{center} 610 | \begin{tikzpicture}[ 611 | level 1/.style={sibling distance=10em}] 612 | \node[sup]{Either[A, B]} 613 | child{node[sub] {Left[A](value: A)}} 614 | child{node[sub]{Right[B](value: B)}} 615 | ; 616 | \end{tikzpicture} 617 | \end{center} 618 | \begin{minted}{scala} 619 | val right: Either[String, Int] = Right(1) 620 | val left: Either[String, Int] = Left("oops") 621 | 622 | // getOrElse 623 | > right.getOrElse(42) 624 | res: Int = 1 625 | > left.getOrElse(42) 626 | res: Int = 42 627 | 628 | // map on left and right side 629 | > right.map(_ + 1) 630 | res: Either[String, Int] = Right(2) 631 | > right.left.map(_.length) 632 | res: Either[Int, Int] = Right(1) 633 | > left.left.map(_.length) 634 | res: Either[Int, Int] = Left(4) 635 | \end{minted} 636 | \section{Try} 637 | \begin{mdframed} 638 | \footnotesize 639 | Interact with Java / Legacy Code where exceptions are thrown, a 640 | means of last resort. 641 | \end{mdframed} 642 | \begin{center} 643 | \begin{tikzpicture}[ 644 | level 1/.style={sibling distance=11em}] 645 | \node[sup]{Try[A]} 646 | child{node[sub] {Failure[A](e: Throwable)}} 647 | child{node[sub]{Success[A](value: A)}} 648 | ; 649 | \end{tikzpicture} 650 | \end{center} 651 | \begin{minted}{scala} 652 | > import scala.util.Try 653 | 654 | > Try { "hello".toInt } 655 | res: Try[Int] = 656 | Failure(java.lang.NumberFormatException) 657 | 658 | > Try { "42".toInt } 659 | res: Try[Int] = Success(42) 660 | \end{minted} 661 | 662 | \section{Collections} 663 | 664 | \begin{mdframed} 665 | \footnotesize 666 | 667 | \par Prefer immutable collections, falling back to a 668 | \mintinline{scala}|var| first and use mutable collections as a 669 | last resort only. Also, prefer \mintinline{scala}|Vector| over 670 | \mintinline{scala}|List|\\. 671 | 672 | \par \textcolor{myred!120}{Warning:} 673 | \mintinline{scala}|Seq| by default allows mutable 674 | implementations, import 675 | \mintinline{scala}|scala.collection.immutable.Seq| instead. 676 | \end{mdframed} 677 | 678 | \begin{minted}{scala} 679 | // Creating a collection via apply: 680 | > List(1, 2, 3) 681 | res: List[Int] = List(1, 2, 3) 682 | > Array('a', 'b') 683 | res: Array[Char] = Array(a, b) 684 | > Map(('a', 1), ('b', 2)) 685 | res: Map[Char, Int] = Map(a -> 1, b -> 2) 686 | 687 | // Importing mutable collections 688 | > import scala.collection.mutable 689 | > mutable.Buffer(1, 2, 3) 690 | res: Buffer[Int] = ArrayBuffer(1, 2, 3) 691 | \end{minted} 692 | 693 | \subsection{Important methods} 694 | 695 | \begin{tabular}{l p{5cm}} 696 | \mintinline{scala}|collect| & filter then map in one \\ 697 | \mintinline{scala}|collectFirst| & \mintinline{scala}|find| with pattern matching \\ 698 | \mintinline{scala}|count| & count elements with predicate \\ 699 | \mintinline{scala}|exists| & check predicate satisfied >= 1 \\ 700 | \mintinline{scala}|find| & find element with predicate \\ 701 | \mintinline{scala}|filter| & filter elements with predicate \\ 702 | \mintinline{scala}|flatMap| & map a function producing a collection \\ 703 | \mintinline{scala}|foldLeft| & recursive traversal \\ 704 | \mintinline{scala}|foldRight| & for right associative ops \\ 705 | \mintinline{scala}|forall| & check predicate holds for all elements \\ 706 | \mintinline{scala}|map| & transform each element \\ 707 | \mintinline{scala}|slice| & select an interval of elements \\ 708 | \mintinline{scala}|take, drop| & remove elements from front/back \\ 709 | \mintinline{scala}|to[Col]| & convert to collection \mintinline{scala}|Col| 710 | \end{tabular} 711 | 712 | \vspace*{02mm} 713 | 714 | \section{Futures} 715 | 716 | \begin{mdframed} 717 | \footnotesize 718 | Don't blindly import Scala's default \texttt{ExecutionContext}, it 719 | is optimized for \textit{CPU-bound} tasks! 720 | \end{mdframed} 721 | 722 | \begin{minted}{scala} 723 | > import scala.concurrent._, duration._ 724 | > import ExecutionContext.Implicits.global 725 | 726 | // Creating an asynchronous computation 727 | > Future { 5 * 2 } 728 | res1: Future[Int] = Future() 729 | 730 | // Modify result with a pure function 731 | > res1.map((n: Int) => n + 11) 732 | res2: Future[Int] = Future() 733 | 734 | // Use flatMap to chain Futures 735 | > res2.flatMap((n: Int) => Future { n * 2 }) 736 | res3: Future[Int] = Future() 737 | 738 | // Register callbacks 739 | > res3.onComplete { 740 | case Success(r) => println(s"Success: $r") 741 | case Failure(e) => println(s"Failure: $e") 742 | } 743 | 744 | // Block thread for result (anti-pattern) 745 | > Await.result(res3, 1.second) 746 | res4: Int = 42 747 | \end{minted} 748 | \subsection{Duration DSL} 749 | 750 | \begin{minted}{scala} 751 | > import scala.concurrent.duration._ 752 | > 5.seconds 753 | res: FiniteDuration = 5 seconds 754 | > 2.hours 755 | res: FiniteDuration = 2 hours 756 | \end{minted} 757 | 758 | \section{Scala Plugin for IntelliJ IDEA} 759 | { 760 | \setlength\tabcolsep{1mm} 761 | 762 | \begin{tabular}{l l l l c} 763 | Show Type Info & \Alt{} & & & \keystroke{=} \\[1mm] 764 | Implicit parameters & \Ctrl{} & & \Shift{} & \keystroke{P} \\[1mm] 765 | Implicit conversions & \Ctrl{} & & \Shift{} & \keystroke{Q} \\[1mm] 766 | ScalaDoc stub & \Ctrl{}& \Alt{} & & \keystroke{Q} \\[1mm] 767 | Refactor This & \Ctrl{}& \Alt{} & \Shift{} & \keystroke{T} \\[1mm] 768 | Rename & & & \Shift{} & \keystroke{F6} \\[1mm] 769 | Inline & \Ctrl{}& \Alt{} & & \keystroke{N} \\[1mm] 770 | Extract Variable & \Ctrl{}& \Alt{} & & \keystroke{V} \\[1mm] 771 | Extract Field & \Ctrl{}& \Alt{} & & \keystroke{F} \\[1mm] 772 | Extract Method & \Ctrl{}& \Alt{} & & \keystroke{M} 773 | \end{tabular} 774 | } 775 | \vspace*{1cm} 776 | \end{multicols*} 777 | \end{document} 778 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: with pkgs; 2 | 3 | let 4 | tex = texlive.combine { 5 | inherit (texlive) 6 | animate 7 | babel 8 | beamer 9 | chngcntr 10 | cleveref 11 | enumitem 12 | etoolbox 13 | excludeonly 14 | exercise 15 | fancyvrb 16 | float 17 | framed 18 | graphviz 19 | ifplatform 20 | keystroke 21 | kpfonts 22 | lineno 23 | listings 24 | ly1 25 | mdframed 26 | media9 27 | microtype 28 | minted 29 | mweights 30 | needspace 31 | ocgx2 32 | overpic 33 | pgf 34 | scheme-medium 35 | soul 36 | sourcesanspro 37 | titlesec 38 | todonotes 39 | upquote 40 | xcolor 41 | xcolor-solarized 42 | xstring 43 | wrapfig; 44 | }; 45 | in 46 | stdenv.mkDerivation { 47 | name = "final-encoding"; 48 | buildInputs = [ 49 | tex 50 | which 51 | graphviz 52 | imagemagick 53 | ] ++ (with pythonPackages; [ 54 | pygments 55 | ]); 56 | } 57 | --------------------------------------------------------------------------------