What Can Scala Puzzlers
Teach Us?
Daniel C. Sobral
Disclaimer #1: "Puzzlers"
● Java Puzzlers (the book/presentations):
○ Weird behavior in Java that is difficult to predict ...
I can't speak for any of the people who
contributed to create and turn Scala into what it
is. Furthermore, if you learn an...
Symbols, operators and punctuation
● What does it mean?
● Where can I find information about it?
● WTF?
The symbol puzzler
Source: Stack Overflow
The Origin of the Symbols
● Punctuation elements of the language
○ @ # ( ) [ ] { } , . ; : ` ' "
● Keywords, reserved symb...
Symbols may be part of the language or come
from external libraries; it can be difficult to tell
where they begin and end;...
Then why?
def f(xs: Array[Int], a: Int, b: Int) =
for (i <- xs.indices)
xs(i) = a * i + b
So that libraries can extend the
language seamlessly
def f(xs: M[T], a: T, b: T) =
for (i <- xs.indices)
xs(i) = a * i + b...
Which still doesn't really justify unicode...
Advice regarding Symbols
● Learn the language:
○ What symbols are "built-in"
○ The syntax rules
● If exploring code using ...
implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = {
new Category[({type λ[α, β...
implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = {
new Category[({type λ[α, β...
implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = {
new Category[({type λ[α, β...
implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = {
new Category[({type λ[α, β...
implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = {
new Category[({type λ[α, β...
The Underscore
● What does it mean?
● Why does it work here but not here?
● WTF?
● It's everywhere! It's the borg operator!
One underscore puzzler
Source: Stack overflow
The meanings of underscore
Source: myself, by way of Stack Overflow
The underscore is Scala's wildcard; it means
"something" or "anything" and even "nothing".
However, it's semantics can be ...
Why?
● ???
● Picking a different symbol for each case
would stretch ASCII
● Picking keywords is not in the spirit of Scala...
Advice regarding underscore
● Intuition does go a long way
● But, again, learn the language
● And, in particular, know the...
Eta, partial function application and
placeholders
● f _
○ an eta expansion: turn method f into an anonymous function.
● f...
_ always picks the tightest non-degenerate
scope it can
Seth Tisue
Erasure
● Where are my types?
● How do I get them back?
● WTF?
Some things that don't work
trait X {
def overload(f: Int => Int)
def overload(f: String => String)
}
Some things that don't work
def f[T](list: List[T]) = list match {
case _: List[Int] => "Ints"
case _: List[String] => "St...
Some things that don't work
class C[T] {
def f(obj: Any) = obj match {
case _: T => "Ours"
case _ => "Not Ours"
}
}
Why?
● JVM does not support "type parameters"
● If Scala added metadata to "eliminate"
erasure, the interaction gap betwee...
Some things that don't work
trait X {
def overload(f: Function1[Int, Int])
def overload(f: Function1[String,
String])
}
Erasure at work
trait X {
def overload(f: Function1)
def overload(f: Function1)
}
Erasure at work
def f(list: List) = list match {
case _: List => "Ints"
case _: List => "Strings"
case _ => "???"
}
Erasure at work
class C {
def f(obj: Any) = obj match {
case _: Any => "Ours"
case _ => "Not Ours"
}
}
A partial solution
class C[T : ClassTag] {
def f(obj: Any) = obj match {
case _: T => "Ours"
case _ => "Not Ours"
}
} thou...
Initialization Order
trait A {
val a: Int
val b = a * 2
}
class B extends A {
val a = 5
println(b)
}
new B
All val’s are initialized in the order they
are found.
Initialization Order
trait A {
val foo: Int
val bar = 10
println("In A: foo: " + foo + ", bar: " + bar)
}
class B extends ...
Initialization Order
In A: foo: 0, bar: 0
In B: foo: 25, bar: 0
In C: foo: 25, bar: 99
Initialization Order
trait A {
val foo: Int
val bar = 10
println("In A: foo: " + foo + ", bar: " + bar)
}
class B extends ...
A val is initialized only once.
Initialization Order
trait A { val x = 5 }
trait B {
val x: Int
println(x * 2)
}
trait C extends A with B
trait D extends ...
Initialization Order
0
10
10
10
Initialization Order
trait A { val x = 5 }
trait B {
val x: Int
println(x * 2)
}
trait C extends A with B
trait D extends ...
Trait linearization...
Advice regarding initialization order
● Learn the _________
Other things to look out for
● Pattern matching on val's and for's
● All sorts of things implicit
● Syntactic sugars, auto...
So, what did I learn?
It seems to me that there's a wide range of
Scala features that depend on the user having
deep knowl...
As for real Puzzlers...
● Site:
○ http://scalapuzzlers.com/
● Book:
○ http://www.artima.com/shop/scala_puzzlers
Upcoming SlideShare
Loading in …5
×

What can scala puzzlers teach us

822
-1

Published on

A look at some of the most common puzzlers faced by Scala beginners.

Published in: Technology, Education
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
822
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
18
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

What can scala puzzlers teach us

  1. 1. What Can Scala Puzzlers Teach Us? Daniel C. Sobral
  2. 2. Disclaimer #1: "Puzzlers" ● Java Puzzlers (the book/presentations): ○ Weird behavior in Java that is difficult to predict or explain ● This presentation: ○ Weird behavior in Scala that confounds beginners ■ (and sometimes experienced programmers) ○ FAQs, not Fun
  3. 3. I can't speak for any of the people who contributed to create and turn Scala into what it is. Furthermore, if you learn anything from this presentation, learn that a perfect understanding of Scala is an unlikely achievement... Disclaimer #2: don't trust me.
  4. 4. Symbols, operators and punctuation ● What does it mean? ● Where can I find information about it? ● WTF?
  5. 5. The symbol puzzler Source: Stack Overflow
  6. 6. The Origin of the Symbols ● Punctuation elements of the language ○ @ # ( ) [ ] { } , . ; : ` ' " ● Keywords, reserved symbols and XML ○ <- => <: >: <% // /* */ _* <? <! ● Normal definitions from libraries ○ <:< =:= ☆ ★ η :/ ● Underscore ○ All of the above!
  7. 7. Symbols may be part of the language or come from external libraries; it can be difficult to tell where they begin and end; they are difficult to search for on the Internet, non-mnemonic and unpronounceable.
  8. 8. Then why? def f(xs: Array[Int], a: Int, b: Int) = for (i <- xs.indices) xs(i) = a * i + b
  9. 9. So that libraries can extend the language seamlessly def f(xs: M[T], a: T, b: T) = for (i <- xs.indices) xs(i) = a * i + b For M and T library-types that support these operations
  10. 10. Which still doesn't really justify unicode...
  11. 11. Advice regarding Symbols ● Learn the language: ○ What symbols are "built-in" ○ The syntax rules ● If exploring code using unknown libraries, ○ Use an IDE to explore it harsh, indeed...
  12. 12. implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = { new Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] { def id[A] = ☆(_ η) def compose[X, Y, Z](f: Kleisli[M, Y, Z], g: Kleisli[M, X, Y]) = f <=< g } } Let's try to figure this one out
  13. 13. implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = { new Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] { def id[A] = ☆(_ η) def compose[X, Y, Z](f: Kleisli[M, Y, Z], g: Kleisli[M, X, Y]) = f <=< g } } Split Scala Syntax from Identifiers
  14. 14. implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = { new Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] { def id[A] = ☆(_ η) def compose[X, Y, Z](f: Kleisli[M, Y, Z], g: Kleisli[M, X, Y]) = f <=< g } } Identify what we are defining
  15. 15. implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = { new Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] { def id[A] = ☆(_ η) def compose[X, Y, Z](f: Kleisli[M, Y, Z], g: Kleisli[M, X, Y]) = f <=< g } } Where we are using our definitions
  16. 16. implicit def KleisliCategory[M[_] : Monad]: Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] = { new Category[({type λ[α, β] = Kleisli[M, α, β]})#λ] { def id[A] = ☆(_ η) def compose[X, Y, Z](f: Kleisli[M, Y, Z], g: Kleisli[M, X, Y]) = f <=< g } } What's left are outside identifiers
  17. 17. The Underscore ● What does it mean? ● Why does it work here but not here? ● WTF? ● It's everywhere! It's the borg operator!
  18. 18. One underscore puzzler Source: Stack overflow
  19. 19. The meanings of underscore Source: myself, by way of Stack Overflow
  20. 20. The underscore is Scala's wildcard; it means "something" or "anything" and even "nothing". However, it's semantics can be widely different, even in similar contexts.
  21. 21. Why? ● ??? ● Picking a different symbol for each case would stretch ASCII ● Picking keywords is not in the spirit of Scala ● They are somewhat intuitive ○ except when they bite you
  22. 22. Advice regarding underscore ● Intuition does go a long way ● But, again, learn the language ● And, in particular, know the difference between these: ○ f _ ○ f(_, y) ○ f(x + _, y)
  23. 23. Eta, partial function application and placeholders ● f _ ○ an eta expansion: turn method f into an anonymous function. ● f(_, y) ○ a partial function application: creates an anonymous function from method f, whose parameters are the ones wholly replaced by underscores. ● f(x + _, y) ○ a placeholder: creates an anonymous function from the expression "x + _", whose parameters are the underscores (and that function gets passed to f).
  24. 24. _ always picks the tightest non-degenerate scope it can Seth Tisue
  25. 25. Erasure ● Where are my types? ● How do I get them back? ● WTF?
  26. 26. Some things that don't work trait X { def overload(f: Int => Int) def overload(f: String => String) }
  27. 27. Some things that don't work def f[T](list: List[T]) = list match { case _: List[Int] => "Ints" case _: List[String] => "Strings" case _ => "???" }
  28. 28. Some things that don't work class C[T] { def f(obj: Any) = obj match { case _: T => "Ours" case _ => "Not Ours" } }
  29. 29. Why? ● JVM does not support "type parameters" ● If Scala added metadata to "eliminate" erasure, the interaction gap between it and Java would be much greater ○ Though things like implicits and default parameters already do it, to some extent ○ At least, implicits and defaults are easy to avoid
  30. 30. Some things that don't work trait X { def overload(f: Function1[Int, Int]) def overload(f: Function1[String, String]) }
  31. 31. Erasure at work trait X { def overload(f: Function1) def overload(f: Function1) }
  32. 32. Erasure at work def f(list: List) = list match { case _: List => "Ints" case _: List => "Strings" case _ => "???" }
  33. 33. Erasure at work class C { def f(obj: Any) = obj match { case _: Any => "Ours" case _ => "Not Ours" } }
  34. 34. A partial solution class C[T : ClassTag] { def f(obj: Any) = obj match { case _: T => "Ours" case _ => "Not Ours" } } though it will still ignore T's type parameters
  35. 35. Initialization Order trait A { val a: Int val b = a * 2 } class B extends A { val a = 5 println(b) } new B
  36. 36. All val’s are initialized in the order they are found.
  37. 37. Initialization Order trait A { val foo: Int val bar = 10 println("In A: foo: " + foo + ", bar: " + bar) } class B extends A { val foo: Int = 25 println("In B: foo: " + foo + ", bar: " + bar) } class C extends B { override val bar = 99 println("In C: foo: " + foo + ", bar: " + bar) } new C Source: Paul Phillips scala-faq by way of scala puzzlers
  38. 38. Initialization Order In A: foo: 0, bar: 0 In B: foo: 25, bar: 0 In C: foo: 25, bar: 99
  39. 39. Initialization Order trait A { val foo: Int val bar = 10 println("In A: foo: " + foo + ", bar: " + bar) } class B extends A { val foo: Int = 25 println("In B: foo: " + foo + ", bar: " + bar) } class C extends B { override val bar = 99 println("In C: foo: " + foo + ", bar: " + bar) } new C
  40. 40. A val is initialized only once.
  41. 41. Initialization Order trait A { val x = 5 } trait B { val x: Int println(x * 2) } trait C extends A with B trait D extends B class E extends D with C { println(x * 2) } class F extends C with D { println(x * 2) } new E new F
  42. 42. Initialization Order 0 10 10 10
  43. 43. Initialization Order trait A { val x = 5 } trait B { val x: Int println(x * 2) } trait C extends A with B trait D extends B class E extends B with D with A with B with C { println(x * 2) } class F extends A with B with C with B with D { println(x * 2) } new E new F
  44. 44. Trait linearization...
  45. 45. Advice regarding initialization order ● Learn the _________
  46. 46. Other things to look out for ● Pattern matching on val's and for's ● All sorts of things implicit ● Syntactic sugars, auto-tupling and the like ● The return keyword
  47. 47. So, what did I learn? It seems to me that there's a wide range of Scala features that depend on the user having deep knowledge of the language when something goes wrong. "What's going on?" seems to be much more common than "How do I do this?"
  48. 48. As for real Puzzlers... ● Site: ○ http://scalapuzzlers.com/ ● Book: ○ http://www.artima.com/shop/scala_puzzlers
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×