Scala for Python Developers – Some basics – Similarities to Python



Scala for Python Developers – Some basics – Similarities to Python

0 0


scala4py-slides

Slides for "Scala for Python Developers" talk

On Github alexbergeron / scala4py-slides

Scala for Python Developers

Alexandre Bergeron Backend Developer @ Wajam @AlexBergeron2

Montreal Python 43 - Artistic Baboon February 10, 2014

About me

  • Bachelor degree in Software Engineering from ETS April 2012
  • Started coding in Python in 2007
  • Started working at Wajam in April 2012
  • Started coding in Scala same month

What is Scala

  • Statically-typed, object-oriented, functional & imperative language
  • Compiles to the JVM - Can call Java libraries transparently
  • Type inference - Types are deducted, no need to specify them
  • Built for concurrency - parrallel collections, actors frameworks, asynchronous Futures

Some basics

Values and variables - strong focus on immutability

// Mutable 
var mutableVariable = "Test" // Type String infered
mutableVariable = "SomethingElse"

// Immutable
val immutableValue = 42 // Type Int infered
//immutableValue = 0 // error: reassignment to val

// We've got Java Arays - we just don't use them a lot
val someArray = Array("Hello", "World")
someArray(1) = "Scala" // They're mutable
println(someAray.mkString(" "))
						

Some basics

Control statements

val meetup = "Montreal Python"
if (meetup.contains("Python")) {
  println("You can see me")
} else {
  // Dead code here
}

// if can also return a value, or be a one-liner
val foo = if (presenterRunningOutOfImagination) bar else baz

try {
  // Something that might throw an exception
} catch {
  case e => // Handle that exception
}
						

Some basics

More control statements

// Scala also has while and do...while loops
// But they're seen as bad practice and used mostly for optimizations
while (someCondition) {
  executeSomeOtherTasks()
}

for (i <- 1 to 5) println(i)
// Syntactic sugar for
(1 to 5).foreach(i => println(i))
						

Some basics

Function declaration

// Our first function
def multiply(x: Int, y: Int): Int = x * y
multiply(2, 3)

// Unit-returning function
def show(i: Int): Unit = {
  println("show(" + i + ")")
}

// Or, as an anonymous function
def anon = (x: Int, y, Int) => x * y // Type Infered
anon(2, 3)

// Functions can take functions as a parameter
def applyOperation(value: Int, oper: Int => Int): Int = oper(value)
						

Some basics

Object-oriented - class, object, extends

abstract class Foo {
  def a: String
}

// Classes can only inherit from one other class
class Bar extends Foo {
  def a = "Bar"
}

// Singleton objects - can behave like a class
object Baz extends Foo {
  def a = "Baz"
}
println(baz.a)
// Companion objects can also be created for existing classes
						

Similarities to Python

Collections

Python

# Lists - Ordered, duplicates allowed
a_list = [1, 2, 3, 4]
# Tuples - Ordered, fixed
a_tuple = (1, 2, 3)
a, b, c = a_tuple
# Sets - Unordered, duplicates not allowed
a_set = {1, 2, 3, 3} # {1, 2, 3}
# Dicts - Binds keys to values
a_dict = {"one": 1, "two": 2}
						

Similarities to Python

Collections

Scala

// Collections are immutable by default
// Mutable versions available
// Seqs - Ordered, duplicates allowed
val seq = Seq(1, 2, 3, 4)
val list = List(1, 2, 3, 4) // 1 :: 2 :: 3 :: 4 :: Nil
// Tuples - Ordered, fixed
val tuple = (1, 2, 3)
val (a, b, c) = tuple
// Sets - Unordered, duplicates not allowed
val set = Set(1, 2, 3, 3) // Set(1, 2, 3)
// Map - Binds keys to values
val map = Map("one" -> 1, "two" -> 2)
						

Similarities to Python

List comprehensions

Python

[x * x for x in range(1, 4)]
# [1, 4, 9]
[x for x in range(1, 10) if x % 3 == 0]
# [3, 6, 9]
[(x, y) for x in range(1,5) for y in range(x, 5) if x + y == 5]
# [(1, 4), (2, 3)]

						

Similarities to Python

For comprehensions

Scala

for (x <- 1 to 3) yield x * x
// Vector(1, 4, 9)

for (x <- 1 to 10 if x % 3 == 0) yield x
// Vector(3, 6, 9)

for {
  x <- 1 until 5
  y <- x until 5
  if x + y == 5
} yield (x, y)
// Vector((1,4), (2,3))
						

Similarities to Python

Functional programming - map, filter

Python

map(lambda x: x * x, range(1, 4))
# [1, 4, 9]
filter(lambda x: x % 3 == 0, range(1,10))
# [3, 6, 9]
from itertools import combinations
def sum_is_five(tuple):
    x, y = tuple
    return x < y and x + y == 5
filter(sum_is_five, combinations(range(1, 5), 2))
# [(1, 4), (2, 3)] 
						

Similarities to Python

Functional programming - map, filter

Scala

(1 to 3).map(x => x * x)
// Vector(1, 4, 9)
(1 to 10).filter(_ % 3 == 0) // Implicit parameter
// Vector(3, 6, 9)
(1 until 5).combinations(2).filter(_.sum == 5).toList
// List(Vector(1, 4), Vector(2, 3))
// Or, closer to what the for-comprehension executes
def sumIsFive(t: (Int, Int)) = {
  val (x, y) = t
  x + y == 5
}
(1 to 5).flatMap(x => (x to 5).map((x, _))).filter(sumIsFive)
// Vector((1,4), (2,3))
						

Distinctions

Pattern matching

// Looks like switch from Java
def sign(n: Int) = n match {
  case 0 => "zero"
  // Supports guards
  case n if < 0 => "negative"
  case _ => "positive
}
						

Distinctions

Pattern matching

// Gets even better with extractors
// Like when pattern matching with lists
def sum(lst: List[Int]): Int = lst match {
  case head :: tail => head + sum(tail)
  case Nil => 0
}
						

Distinctions

Option - Avoiding nulls

// Option[A] type has two possible values
// Some(value: A)
// None
// This allows to avoid nulls and NullPointerException
def greet(name: Option[String]): Unit = {
  println("Hello " + name.getOrElse("world"))
}
greet(Some("Python"))
greet(None)
						

Distinctions

Option - Avoiding nulls

// Option also fits into pattern matching
def respond(result: Option[String]): Unit = result match {
  case Some(r) => println("Response sent: " + r)
  case None => println("No response sent")
}
						

Distinctions

Try - Avoiding calls to try

// Like Option, Try[A] has two possible values
// Success(value: A)
// Failure(t: Throwable)
// And it can be used with pattern matching
Try(4 / 2) // Success(2)
Try(1 / 0) // Failure(java.lang.ArithmeticException: / by zero)
						

Distinctions

case class - Easy way to create class that integrates with Pattern Matching

case class Person(name: String, city: String, job: Option[String])

// Every parameters in that constructor is now an immutable field
def makeStringForPerson(p: Person) = {
  println(p.name + " - " p.job,getOrElse("unemployed") + " in " + p.city)
}

// You can also easily clone a case class
def moveTo(p: Person, c: String) = p.copy(city = c)

// As you'll see, you can also have case objects
						

Distinctions

Traits - Allows to inherit from multiple traits with implementations

trait A {
  def toImplement(): Int
}
trait B {
  val value = 42
  def implemented() = value
}
class C extends A with B {
  def toImplement() = implemented()
}
						

Distinctions

Traits - Allows to inherit from multiple traits with implementations

// sealed = you can't implement this trait outside of this file
// The + in front of means it's covariant.
sealed trait Option[+A] {
  def getOrElse(value: A) = this match {
    case Some(v) => v
    case None => value
  }
}
case class Some[+A](value: A) extends Option[A]
case object None extends Option[Nothing] // Nothing = Bottom type 
						

Points of contention

  • Static typing vs Dynamic Typing
  • Code nesting vs Zen of Python (PEP-20)
  • Readability from line conciseness and explicit types vs short methods and naming things
  • More than one way to do it vs only one way to do it

Read more about Scala

Questions?

Thanks for listening

Made with reveal.js

0