SlideShare a Scribd company logo
Analysing Scala Puzzlers:
Essential and Accidental
Complexity in Scala
Andrew Phillips & Nermin Serifovic
@ScalaPuzzlers
About us
Andrew
● Lots of enterprise software
development on high-
performance systems
● Active open source contributor
and committer
Nermin
Co-organizer of Boston Area Scala
Enthusiasts
Co-instructor of Concurrent
Programming in Scala
Maintainers of scalapuzzlers.com and
authors of Scala Puzzlers
Agenda
Introduction
Puzzler Clusters
Reflections & Conclusions
Introduction
What are we trying to do here?
● We’ve been collecting examples of “surprising”
Scala code for a couple of years now
● We thought it was time to see if we could
identify some patterns
● Looking at the results, we tried to ask
ourselves: is the “puzzler cost” of a particular
language area outweighed by the “feature
benefit”
What are we trying to do here?
The clusters, based on 46 puzzlers:
● Cluster 1: Object-orientation
● Cluster 2: Collections
● Cluster 3: Syntax sugar
● Cluster 4: The type system
●Cluster 5: Functional programming
Cluster 1: Object-
orientation
15 puzzlers
What’s the issue?
Scala aims to combine functional and object-
oriented features...and play nicely with Java on
top of that.
Gotcha: Java peeking in
def value: Int = {
def one(x: Int): Int = { return x; 1 }
val two = (x: Int) => { return x; 2 }
1 + one(2) + two(3)
}
println(value)
Gotcha: Initialization in subclasses
class A {
type X // equivalent to X <: Any
var x: X = _
}
class B extends A { type X = Int }
val b = new B
println(b.x)
val bX = b.x
println(bX)
Gotcha: Constructors
object HipNTrendyMarket extends App { // now extends App!
implicit val normalMarkup = new Markup
Console println makeLabel(3)
implicit val touristMarkup = new TouristMarkup
Console println makeLabel(5)
}
object OldSkoolMarket {
def main(args: Array[String]): Unit = {
implicit val normalMarkup = new Markup
Console println makeLabel(3)
implicit val touristMarkup = new TouristMarkup
Console println makeLabel(5)
}
}
Moral of the story
Try to prevent non-idiomatic elements from
seeping though Scala/Java boundaries in
your code
If you’re using a lot of inheritance, study the
rules for variable initialization
Class body != method body
Cluster 2: Collections
9 puzzlers
Collections are powerful...and sometimes
puzzling
What’s the issue?
Gotcha: collections are functions!
Most commonly used collections are instances
of Function1:
List: index => element
Set: element => Boolean
Map: key => value
Gotcha: collections are functions!
This comes handy in many situations, such as:
val daysOfWeek = Map("Mon" -> 1, "Tue" -> 2, "Wed" -> 3,
"Thu" -> 4, "Fri" -> 5, "Sat" -> 6, "Sun" -> 7)
def foo(day: String, daysOfWeek: String => Int) =
println(s"${day} is the ${daysOfWeek(day)}. day of the week")
scala> foo("Mon", daysOfWeek)
Mon is the 1. day of the week
Gotcha: collections are functions!
Sometimes, this produces undesired effects...
def pad2(sb: StringBuilder, width: Int) = {
1 to width - sb.length foreach { sb append '*' }
sb
}
Gotcha: collections are functions!
Sometimes, this produces undesired effects...
def pad2(sb: StringBuilder, width: Int) = {
1 to width - sb.length foreach { sb append '*' }
sb
}
// 1 to (width - sb.length) foreach (_ => sb append '*')
Gotcha: convenience (?) methods
val ints = Map(1 -> List(1, 2, 3, 4, 5))
val bits = ints map { case (k, v) => (k, v.toIterator) }
val nits = ints mapValues (_.toIterator)
scala> print(bits(1).next, bits(1).next)
(1,2)
scala> print(nits(1).next, nits(1).next)
(1,1)
// keys are mapped to key => this(key).toIterator
Gotcha: convenience (?) methods
import collection.mutable.Queue
val goodies: Map[String, Queue[String]] = Map().withDefault(_ =>
Queue("No superheros here. Keep looking."))
val baddies: Map[String, Queue[String]] =
Map().withDefaultValue(Queue("No monsters here. Lucky you."))
println(goodies("kitchen").dequeue)
println(baddies("in attic").dequeue)
println(goodies("dining room").dequeue)
println(baddies("under bed").dequeue)
Moral of the story
Scala collections are powerful
Can be passed where Function1 is expected,
which is a useful feature, but also one to be
careful about
Pay special attention when dealing with
convenience methods that appear similar -
not all of them behave intuitively
Cluster 3:
Syntax sugar
11 puzzlers
Scala promotes elegant, concise coding style.
At the same time, the spec tries to remove
complexity from the compilation process early.
This results in a lot of rewriting of expressions.
What’s the issue?
Gotcha: placeh_lders
List(1, 2).map { i => println("Hi"); i + 1 }
List(1, 2).map { println("Hi"); _ + 1 }
Gotcha: for expressions
val xs = Seq(Seq("a", "b", "c"), Seq("d", "e", "f"), Seq("g",
"h"), Seq("i", "j", "k"))
val ys = for (Seq(x, y, z) <- xs) yield x + y + z
val zs = xs map { case Seq(x, y, z) => x + y + z }
Gotcha: implicit magic
case class Card(number: Int, suit: String = "clubs") {
val value = (number % 13) + 1 // ace = 1, king = 13
def isInDeck(implicit deck: List[Card]) = deck contains this
}
implicit val deck = List(Card(1, "clubs"))
implicit def intToCard(n: Int) = Card(n)
println(1.isInDeck)
Moral of the story
Beware when the syntax sugar for similar but
different things looks almost identical
Learn the details of more complex
desugarings, e.g. how for expressions are
translated
There are too many ways to do (almost) the
same thing with implicits - stick to one style
Cluster 4:
The Type System
7 puzzlers
By design, the Scala compiler tries to be
tolerant and “make the most of” an expression
by slightly transforming it in various ways.
In lots of situations, this goes against
programmer’s intentions
What’s the issue?
Gotcha: Type widening
val zippedLists = (List(1,3,5), List(2,4,6)).zipped
val result = zippedLists.find(_._1 > 10).getOrElse(10)
result: Any = 10
def List.find(p: (A) ⇒ Boolean): Option[A]
def Option.getOrElse[B >: A](default: ⇒ B): B
Type B is inferred to be Any - the least common
supertype between Tuple2 and Int
Gotcha: Type widening
For explicitly defined type hierarchies, this works as
intended:
scala> trait Animal
scala> class Dog extends Animal
scala> class Cat extends Animal
scala> val dog = Option(new Dog())
scala> val cat = Option(new Cat())
scala> dog.orElse(cat)
res0: Option[Animal] = Some(Dog@7d8995e)
Gotcha: Auto-tupling
def foo(any: Any) = println(any)
foo(“a”, “b”, “c”)
(a, b, c)
The compiler tries to pack all arguments into a
tuple and applies foo to that. This is the last
thing which is tried (after default arguments).
Gotcha: Type adaption galore
val numbers = List("1", "2").toSet() + "3"
println(numbers)
false3
def List.toSet[B >: A]: Set[B]
List("1", "2").toSet.apply() // apply() == contains()
Compiler implicitly inserts Unit value () and infers
supertype Any:
List("1", "2").toSet[Any].apply(())
Gotcha: Type adaption galore
●Not desirable in general
●Too much “magic” involved
●Automatic () insertion deprecated in 2.11
Moral of the story
We often wish the compiler was more strict
and threw an error in such cases
We should take advantage of static analysis
tools available (WartRemover, compiler
flags, linters, etc.)
Extensive unit testing of statically typed code
is still necessary
Moral of the story
Take advantage of the compiler flags:
-deprecation,
-unchecked,
-feature,
-Xfatal-warnings,
-Xlint
Cluster 5:
Functional programming
5 puzzlers
What’s the issue?
There are lots of ways you can specify and call
functions...
Gotcha: Partial application
var x = 0
def counter = { x += 1; x }
def add(a: Int)(b: Int) = a + b
val adder1 = add(counter)(_)
val adder2 = add(counter) _
println("x = " + x)
println(adder1(10))
println("x = " + x)
println(adder2(10))
println("x = " + x)
Gotcha: Native function syntax
val isEven = PartialFunction[Int, String] {
case n if n % 2 == 0 => "Even"
}
Moral of the story
There are many flavours of partial application
that do slightly different things - try to stick to
a few
If you are going to use native function syntax,
ensure you know exactly what you’re
creating
Reflections &
Conclusions
●Java interoperability comes at a high cost
●It pays to study the rules of common
desugarings closely
●Implicits up the level of “magic” in your code
quite significantly
●Read the ScalaDoc carefully
●Don’t skimp on unit testing
TL;DR: agree on :
● Scala features you really need; use linters,
code review etc. to catch the others
●common code style in areas where the
language allows multiple options
Questions?
Thank you!
Be the one to submit the next puzzler at
scalapuzzlers.com!

More Related Content

What's hot (20)

PDF
Property based Testing - generative data & executable domain rules
Debasish Ghosh
 
PDF
Why Haskell
Susan Potter
 
PDF
A Sceptical Guide to Functional Programming
Garth Gilmour
 
PDF
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
Ruslan Shevchenko
 
PPTX
A Brief Intro to Scala
Tim Underwood
 
PDF
Scala introduction
vito jeng
 
PPTX
Scala fundamentals
Alfonso Ruzafa
 
ODP
A Tour Of Scala
fanf42
 
PPT
Scala presentation by Aleksandar Prokopec
Loïc Descotte
 
PPTX
Joy of scala
Maxim Novak
 
PDF
Introduction to scala
Michel Perez
 
PPTX
Scala for curious
Tim (dev-tim) Zadorozhniy
 
PDF
Scala collections api expressivity and brevity upgrade from java
IndicThreads
 
PDF
Demystifying functional programming with Scala
Denis
 
PDF
Scala vs java 8
François Sarradin
 
PPTX
ScalaDays 2013 Keynote Speech by Martin Odersky
Typesafe
 
PPTX
Scala on Android
Jakub Kahovec
 
PDF
scala.reflect, Eugene Burmako
Vasil Remeniuk
 
PPT
Scala introduction
Yardena Meymann
 
PDF
Metaprogramming in Scala 2.10, Eugene Burmako,
Vasil Remeniuk
 
Property based Testing - generative data & executable domain rules
Debasish Ghosh
 
Why Haskell
Susan Potter
 
A Sceptical Guide to Functional Programming
Garth Gilmour
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
Ruslan Shevchenko
 
A Brief Intro to Scala
Tim Underwood
 
Scala introduction
vito jeng
 
Scala fundamentals
Alfonso Ruzafa
 
A Tour Of Scala
fanf42
 
Scala presentation by Aleksandar Prokopec
Loïc Descotte
 
Joy of scala
Maxim Novak
 
Introduction to scala
Michel Perez
 
Scala for curious
Tim (dev-tim) Zadorozhniy
 
Scala collections api expressivity and brevity upgrade from java
IndicThreads
 
Demystifying functional programming with Scala
Denis
 
Scala vs java 8
François Sarradin
 
ScalaDays 2013 Keynote Speech by Martin Odersky
Typesafe
 
Scala on Android
Jakub Kahovec
 
scala.reflect, Eugene Burmako
Vasil Remeniuk
 
Scala introduction
Yardena Meymann
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Vasil Remeniuk
 

Viewers also liked (17)

PDF
Valentine's Day Wine Menu
Laura Bull
 
DOC
T.s.16 piragua 1
Caterina Ferreres Català
 
PPTX
Watching wrc 2015 rally poland live
romannable
 
PPTX
Wrc 2015 rally poland
romannable
 
PPTX
Desarrollo sustentable
alejandro rangel
 
PDF
Deployment is the new build
Andrew Phillips
 
PDF
My role
nkadzi elvis
 
PPTX
mapa-conceptual-actividad1-grupo6
yoneireht paola briceño perez
 
PPT
Diagrama Slideshare
yoani19
 
PPSX
Fenomenosydesastresnaturales final 1.0
christian pablo vicente bedoya
 
DOC
Kelopok kursi amer
NICO AKBAR
 
PPTX
Las políticas alimentarias
Eduardo Galaviz
 
PDF
Metrics-driven Continuous Delivery
Andrew Phillips
 
PDF
Comunicación 1.0 y 2.0: Aplicación en el ámbito de la SST
Community Manager Full Audit
 
PDF
Know your cirrus from your cumulus (with notes)
Andrew Phillips
 
DOC
Ts 16 observacio 5
Caterina Ferreres Català
 
PPTX
Mapa conceptual proyectos
yoneireht paola briceño perez
 
Valentine's Day Wine Menu
Laura Bull
 
T.s.16 piragua 1
Caterina Ferreres Català
 
Watching wrc 2015 rally poland live
romannable
 
Wrc 2015 rally poland
romannable
 
Desarrollo sustentable
alejandro rangel
 
Deployment is the new build
Andrew Phillips
 
My role
nkadzi elvis
 
mapa-conceptual-actividad1-grupo6
yoneireht paola briceño perez
 
Diagrama Slideshare
yoani19
 
Fenomenosydesastresnaturales final 1.0
christian pablo vicente bedoya
 
Kelopok kursi amer
NICO AKBAR
 
Las políticas alimentarias
Eduardo Galaviz
 
Metrics-driven Continuous Delivery
Andrew Phillips
 
Comunicación 1.0 y 2.0: Aplicación en el ámbito de la SST
Community Manager Full Audit
 
Know your cirrus from your cumulus (with notes)
Andrew Phillips
 
Ts 16 observacio 5
Caterina Ferreres Català
 
Mapa conceptual proyectos
yoneireht paola briceño perez
 
Ad

Similar to Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexity in Scala" (20)

PPTX
Scala Intro
Alexey (Mr_Mig) Migutsky
 
PPTX
flatMap Oslo presentation slides
Martin Odersky
 
PPTX
Flatmap
Martin Odersky
 
PDF
Introductiontoprogramminginscala
Amuhinda Hungai
 
PDF
Programming in Scala - Lecture Three
Angelo Corsaro
 
PPTX
Scala - The Simple Parts, SFScala presentation
Martin Odersky
 
PDF
Scala. Introduction to FP. Monads
Kirill Kozlov
 
PDF
Introduction to Scala : Clueda
Andreas Neumann
 
PDF
Meet scala
Wojciech Pituła
 
ODP
Functional programming with Scala
Neelkanth Sachdeva
 
PDF
Frp2016 3
Kirill Kozlov
 
PPTX
Scala training workshop 02
Nguyen Tuan
 
PPTX
Principles of functional progrmming in scala
ehsoon
 
PDF
Getting Started With Scala
Meetu Maltiar
 
ODP
Scala ntnu
Alf Kristian Støyle
 
PDF
An Introduction to Scala (2014)
William Narmontas
 
PDF
Scala intro workshop
Fredrik Vraalsen
 
PDF
Scala Quick Introduction
Damian Jureczko
 
PDF
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
ODP
Functional Programming With Scala
Knoldus Inc.
 
flatMap Oslo presentation slides
Martin Odersky
 
Introductiontoprogramminginscala
Amuhinda Hungai
 
Programming in Scala - Lecture Three
Angelo Corsaro
 
Scala - The Simple Parts, SFScala presentation
Martin Odersky
 
Scala. Introduction to FP. Monads
Kirill Kozlov
 
Introduction to Scala : Clueda
Andreas Neumann
 
Meet scala
Wojciech Pituła
 
Functional programming with Scala
Neelkanth Sachdeva
 
Frp2016 3
Kirill Kozlov
 
Scala training workshop 02
Nguyen Tuan
 
Principles of functional progrmming in scala
ehsoon
 
Getting Started With Scala
Meetu Maltiar
 
An Introduction to Scala (2014)
William Narmontas
 
Scala intro workshop
Fredrik Vraalsen
 
Scala Quick Introduction
Damian Jureczko
 
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
Functional Programming With Scala
Knoldus Inc.
 
Ad

More from Andrew Phillips (11)

PDF
Spinnaker Summit 2019: Where are we heading? The Future of Continuous Delivery
Andrew Phillips
 
PDF
Docker New York City: From GitOps to a scalable CI/CD Pattern for Kubernetes
Andrew Phillips
 
PDF
Continuous Delivery NYC: From GitOps to an adaptable CI/CD Pattern for Kubern...
Andrew Phillips
 
PDF
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
Andrew Phillips
 
PDF
OpenDev 2018: "Open CD for Open Infrastructure - Hybrid and Multi-Cloud Deplo...
Andrew Phillips
 
PDF
New York Kubernetes: CI/CD Patterns for Kubernetes
Andrew Phillips
 
PDF
nycdevops: "Breaking Down the Prod/Dev Wall"
Andrew Phillips
 
PPTX
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
Andrew Phillips
 
PPTX
The Multiple Dimensions of Cross-Cloud Computing
Andrew Phillips
 
PDF
Implementing Continuous Deployment
Andrew Phillips
 
PDF
Know your cirrus from your cumulus
Andrew Phillips
 
Spinnaker Summit 2019: Where are we heading? The Future of Continuous Delivery
Andrew Phillips
 
Docker New York City: From GitOps to a scalable CI/CD Pattern for Kubernetes
Andrew Phillips
 
Continuous Delivery NYC: From GitOps to an adaptable CI/CD Pattern for Kubern...
Andrew Phillips
 
Spinnaker Summit 2018: CI/CD Patterns for Kubernetes with Spinnaker
Andrew Phillips
 
OpenDev 2018: "Open CD for Open Infrastructure - Hybrid and Multi-Cloud Deplo...
Andrew Phillips
 
New York Kubernetes: CI/CD Patterns for Kubernetes
Andrew Phillips
 
nycdevops: "Breaking Down the Prod/Dev Wall"
Andrew Phillips
 
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
Andrew Phillips
 
The Multiple Dimensions of Cross-Cloud Computing
Andrew Phillips
 
Implementing Continuous Deployment
Andrew Phillips
 
Know your cirrus from your cumulus
Andrew Phillips
 

Recently uploaded (20)

PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
PDF
AI Agents in the Cloud: The Rise of Agentic Cloud Architecture
Lilly Gracia
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
PPTX
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
PDF
NASA A Researcher’s Guide to International Space Station : Physical Sciences ...
Dr. PANKAJ DHUSSA
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
AI Agents in the Cloud: The Rise of Agentic Cloud Architecture
Lilly Gracia
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
UiPath DevConnect 2025: Agentic Automation Community User Group Meeting
DianaGray10
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
NASA A Researcher’s Guide to International Space Station : Physical Sciences ...
Dr. PANKAJ DHUSSA
 

Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexity in Scala"

  • 1. Analysing Scala Puzzlers: Essential and Accidental Complexity in Scala Andrew Phillips & Nermin Serifovic @ScalaPuzzlers
  • 2. About us Andrew ● Lots of enterprise software development on high- performance systems ● Active open source contributor and committer Nermin Co-organizer of Boston Area Scala Enthusiasts Co-instructor of Concurrent Programming in Scala Maintainers of scalapuzzlers.com and authors of Scala Puzzlers
  • 5. What are we trying to do here? ● We’ve been collecting examples of “surprising” Scala code for a couple of years now ● We thought it was time to see if we could identify some patterns ● Looking at the results, we tried to ask ourselves: is the “puzzler cost” of a particular language area outweighed by the “feature benefit”
  • 6. What are we trying to do here? The clusters, based on 46 puzzlers: ● Cluster 1: Object-orientation ● Cluster 2: Collections ● Cluster 3: Syntax sugar ● Cluster 4: The type system ●Cluster 5: Functional programming
  • 8. What’s the issue? Scala aims to combine functional and object- oriented features...and play nicely with Java on top of that.
  • 9. Gotcha: Java peeking in def value: Int = { def one(x: Int): Int = { return x; 1 } val two = (x: Int) => { return x; 2 } 1 + one(2) + two(3) } println(value)
  • 10. Gotcha: Initialization in subclasses class A { type X // equivalent to X <: Any var x: X = _ } class B extends A { type X = Int } val b = new B println(b.x) val bX = b.x println(bX)
  • 11. Gotcha: Constructors object HipNTrendyMarket extends App { // now extends App! implicit val normalMarkup = new Markup Console println makeLabel(3) implicit val touristMarkup = new TouristMarkup Console println makeLabel(5) } object OldSkoolMarket { def main(args: Array[String]): Unit = { implicit val normalMarkup = new Markup Console println makeLabel(3) implicit val touristMarkup = new TouristMarkup Console println makeLabel(5) } }
  • 12. Moral of the story Try to prevent non-idiomatic elements from seeping though Scala/Java boundaries in your code If you’re using a lot of inheritance, study the rules for variable initialization Class body != method body
  • 14. Collections are powerful...and sometimes puzzling What’s the issue?
  • 15. Gotcha: collections are functions! Most commonly used collections are instances of Function1: List: index => element Set: element => Boolean Map: key => value
  • 16. Gotcha: collections are functions! This comes handy in many situations, such as: val daysOfWeek = Map("Mon" -> 1, "Tue" -> 2, "Wed" -> 3, "Thu" -> 4, "Fri" -> 5, "Sat" -> 6, "Sun" -> 7) def foo(day: String, daysOfWeek: String => Int) = println(s"${day} is the ${daysOfWeek(day)}. day of the week") scala> foo("Mon", daysOfWeek) Mon is the 1. day of the week
  • 17. Gotcha: collections are functions! Sometimes, this produces undesired effects... def pad2(sb: StringBuilder, width: Int) = { 1 to width - sb.length foreach { sb append '*' } sb }
  • 18. Gotcha: collections are functions! Sometimes, this produces undesired effects... def pad2(sb: StringBuilder, width: Int) = { 1 to width - sb.length foreach { sb append '*' } sb } // 1 to (width - sb.length) foreach (_ => sb append '*')
  • 19. Gotcha: convenience (?) methods val ints = Map(1 -> List(1, 2, 3, 4, 5)) val bits = ints map { case (k, v) => (k, v.toIterator) } val nits = ints mapValues (_.toIterator) scala> print(bits(1).next, bits(1).next) (1,2) scala> print(nits(1).next, nits(1).next) (1,1) // keys are mapped to key => this(key).toIterator
  • 20. Gotcha: convenience (?) methods import collection.mutable.Queue val goodies: Map[String, Queue[String]] = Map().withDefault(_ => Queue("No superheros here. Keep looking.")) val baddies: Map[String, Queue[String]] = Map().withDefaultValue(Queue("No monsters here. Lucky you.")) println(goodies("kitchen").dequeue) println(baddies("in attic").dequeue) println(goodies("dining room").dequeue) println(baddies("under bed").dequeue)
  • 21. Moral of the story Scala collections are powerful Can be passed where Function1 is expected, which is a useful feature, but also one to be careful about Pay special attention when dealing with convenience methods that appear similar - not all of them behave intuitively
  • 23. Scala promotes elegant, concise coding style. At the same time, the spec tries to remove complexity from the compilation process early. This results in a lot of rewriting of expressions. What’s the issue?
  • 24. Gotcha: placeh_lders List(1, 2).map { i => println("Hi"); i + 1 } List(1, 2).map { println("Hi"); _ + 1 }
  • 25. Gotcha: for expressions val xs = Seq(Seq("a", "b", "c"), Seq("d", "e", "f"), Seq("g", "h"), Seq("i", "j", "k")) val ys = for (Seq(x, y, z) <- xs) yield x + y + z val zs = xs map { case Seq(x, y, z) => x + y + z }
  • 26. Gotcha: implicit magic case class Card(number: Int, suit: String = "clubs") { val value = (number % 13) + 1 // ace = 1, king = 13 def isInDeck(implicit deck: List[Card]) = deck contains this } implicit val deck = List(Card(1, "clubs")) implicit def intToCard(n: Int) = Card(n) println(1.isInDeck)
  • 27. Moral of the story Beware when the syntax sugar for similar but different things looks almost identical Learn the details of more complex desugarings, e.g. how for expressions are translated There are too many ways to do (almost) the same thing with implicits - stick to one style
  • 28. Cluster 4: The Type System 7 puzzlers
  • 29. By design, the Scala compiler tries to be tolerant and “make the most of” an expression by slightly transforming it in various ways. In lots of situations, this goes against programmer’s intentions What’s the issue?
  • 30. Gotcha: Type widening val zippedLists = (List(1,3,5), List(2,4,6)).zipped val result = zippedLists.find(_._1 > 10).getOrElse(10) result: Any = 10 def List.find(p: (A) ⇒ Boolean): Option[A] def Option.getOrElse[B >: A](default: ⇒ B): B Type B is inferred to be Any - the least common supertype between Tuple2 and Int
  • 31. Gotcha: Type widening For explicitly defined type hierarchies, this works as intended: scala> trait Animal scala> class Dog extends Animal scala> class Cat extends Animal scala> val dog = Option(new Dog()) scala> val cat = Option(new Cat()) scala> dog.orElse(cat) res0: Option[Animal] = Some(Dog@7d8995e)
  • 32. Gotcha: Auto-tupling def foo(any: Any) = println(any) foo(“a”, “b”, “c”) (a, b, c) The compiler tries to pack all arguments into a tuple and applies foo to that. This is the last thing which is tried (after default arguments).
  • 33. Gotcha: Type adaption galore val numbers = List("1", "2").toSet() + "3" println(numbers) false3 def List.toSet[B >: A]: Set[B] List("1", "2").toSet.apply() // apply() == contains() Compiler implicitly inserts Unit value () and infers supertype Any: List("1", "2").toSet[Any].apply(())
  • 34. Gotcha: Type adaption galore ●Not desirable in general ●Too much “magic” involved ●Automatic () insertion deprecated in 2.11
  • 35. Moral of the story We often wish the compiler was more strict and threw an error in such cases We should take advantage of static analysis tools available (WartRemover, compiler flags, linters, etc.) Extensive unit testing of statically typed code is still necessary
  • 36. Moral of the story Take advantage of the compiler flags: -deprecation, -unchecked, -feature, -Xfatal-warnings, -Xlint
  • 38. What’s the issue? There are lots of ways you can specify and call functions...
  • 39. Gotcha: Partial application var x = 0 def counter = { x += 1; x } def add(a: Int)(b: Int) = a + b val adder1 = add(counter)(_) val adder2 = add(counter) _ println("x = " + x) println(adder1(10)) println("x = " + x) println(adder2(10)) println("x = " + x)
  • 40. Gotcha: Native function syntax val isEven = PartialFunction[Int, String] { case n if n % 2 == 0 => "Even" }
  • 41. Moral of the story There are many flavours of partial application that do slightly different things - try to stick to a few If you are going to use native function syntax, ensure you know exactly what you’re creating
  • 43. ●Java interoperability comes at a high cost ●It pays to study the rules of common desugarings closely ●Implicits up the level of “magic” in your code quite significantly ●Read the ScalaDoc carefully ●Don’t skimp on unit testing
  • 44. TL;DR: agree on : ● Scala features you really need; use linters, code review etc. to catch the others ●common code style in areas where the language allows multiple options
  • 46. Thank you! Be the one to submit the next puzzler at scalapuzzlers.com!