Scala Overview for Python Programmers (Draft)

This is a gentle overview of Scala for people with a Python background. It started as a collection of notes, and is by no means exhaustive or claims any authority whatsoever. It does assume a decent knowledge of Python (independant of version 2 or 3), while aiming to provide side-by-side comparisons of Scala and Python source code. Any feedback or improvements are highly welcome!

Motivation

Scala is becoming ever more popular as a successor of Java which, in turn, was designed as a better, C/C++ and iterated the mantra of "build once, run everywhere" on the basis of its JVM technology. Today Scala flourishes also because Java is perceived by many as an inflexible behemoth with an uncertain future in the hands of a single company with unclear interest in Open Source technology. And Java is perceived to no longer fit the bill anymore as an end-user language in today's world of big data and map-reduce paradigms. Scala adds the functional features fitting these new paradigms while reducing lots of the annoying Java syntax. As a result it is very popular in the big data and machine learning world of today.

Many authors on the web emphasize how much Scala is, in fact, unlike Java, referring mostly to syntax and functional features. Bruce Eckel regards Scala as a "static language that feels dynamic" and even "Pythonic". And David Mertz has pointed out how much is already possible in terms of functional programming in Python already. All this makes it appear interesting to look more deeply at Scala from a Python rather than the usual Java perspective.

About this Notebook

There are many sources on the web for learning about Scala. But few allow to play as interactively and joyfully with a programming language in an explorative way like Jupyter notebooks. Originally something like a REPL on steroids for Python only (and much inspired by Mathematica and MATLAB), Jupyter today supports ca. 40 languages, and has become the de-facto interactive, explorative programming environment for data scientists and other professionals. Paying tribute to this fact, the Apache foundation has started developping a Scala kernel extension for Jupyter named Apache Toree which is used in this notebook.

The REPL included with Scala is a useful command-line interpreter, much like the standard Python interpreter shell, but without many bells and whistles. For the more graphically minded users some Scala IDEs provide the concept of a worksheet in which you write code in one column and see its output and type information in a second column. Jupyter notebooks go way beyond that, blending interactive code, visualisations and text cells like in Donald E. Knuth's famous concept of Literate Programming, with tons of plugins provided by third parties.

The easiest way to interactively run this notebook (named "scala_for_pythoneers.ipynb") is in an online version of Jupyter (formerly tmpnb.org, a free service by RackSpace). Just create a new session by opening the page in a browser, click on the white "Upload" button, select this notebook's file name on your local computer, click on the blue "Upload" button in the then newly added row at the top for this file, and finally click its name in the list of all available files. Then you can edit and execute cells and experiment with the notebook. But beware that any changes will be lost after you disconnect from this session! An alternative way of running this locally is given in an appendix on Local Installation.

Comments

Scala has single line and multi-line comments. The latter doesn't exist in Python, but these are often emulated using multi-line strings in tripple-quotes, either single or double ones.

The expressions in the cells below (here the literal number 42) need to be there only to please the Scala kernel for Jupyter. Otherwise it will create an error for cells that contain a comment only. This is likely a buglet that will disappear in future versions.


In [1]:
42 // inline one-line comment


Out[1]:
42

In [2]:
// a one-line comment
42


Out[2]:
42

In [3]:
/* a multi-
   line
   comment */
42


Out[3]:
42

Print

Like any other programming language Scala also has a function to print something somewhere, in some a shell, on the screen, etc. This is print and a variation, println (the latter adding a trailing newline). These are not used a lot in this notebook because inside a cell an expression's result is evaluated and printed automatically:


In [4]:
40 + 2


Out[4]:
42

In [5]:
print(40 + 2)


42

In [6]:
println(40 + 2)


42

Beware that the Scala REPL will provide more detailed output compared to Apache Toree (especially about types) like this, but maybe the latter will catch-up at some time:

scala> 40 + 2
res12: Int = 42

Semicolons

Scala, like Python, doesn't require semicolons at the end of lines, but you can use them between statements if you absolutely feel like:


In [7]:
println(40)
println(42)


40
42

In [8]:
println(40);
println(42);


40
42

In [9]:
println(40); println(42)


40
42

Literals

This is a short overview of Scala datastructures available as literals. All of them are treated in more detail in the section on Basic Datatypes.


In [10]:
true


Out[10]:
true

In [11]:
false


Out[11]:
false

In [12]:
42


Out[12]:
42

In [13]:
3.14


Out[13]:
3.14

In [14]:
"some string"


Out[14]:
some string

In [15]:
"""
multi-line
string
"""


Out[15]:
"
multi-line
string
"

In [16]:
"""
multi-line
string with ümläüts 
"""


Out[16]:
"
multi-line
string with ümläüts
"

In [17]:
'A'


Out[17]:
A

In [18]:
("my tuple", true, 42)


Out[18]:
(my tuple,true,42)

Scala provides explicit symbols for "interning" strings, basically for accelerating string comparisons. Python does that partly implicitly for short strings and partly on demand with a function named intern() (in Python 3: sys.intern().


In [19]:
'symbol


Out[19]:
'symbol

In [20]:
val sym = Symbol("hello world")

In [21]:
sym


Out[21]:
'hello world

Scala has XML support built-into the language, even as literals. Yes, that's right. You can happily type XML content in arbitrary tags:


In [22]:
val para = <p>Hello, XML world!</p>

In [23]:
para


Out[23]:
<p>Hello, XML world!</p>

Functions without a name can be considered function literals. See more in section on Anonymous Functions


In [24]:
(x: Int) => x + 1


Out[24]:
<function1>

Variables and Values

Variables come in mutable and immutable versions, meaning one can either reassign their values or not, respectively. They are declared with var and val, respectively (use this menemonic device: VARiable versus VALue). So, variables with a var declarator are mutable:


In [25]:
var x = 42

In [26]:
x = 43

In [27]:
x


Out[27]:
43

But those declared as val ("values") are immutable, ie. constant. Trying to reassign a value to them raises an error:


In [28]:
val x = 42

In [29]:
x = 43


Out[29]:
Name: Compile Error
Message: <console>:19: error: reassignment to val
       x = 43
         ^
StackTrace: 

Type Declarations

Scala uses type inference to derive types whenever it can, but, sure enough, one can provide an explicit type where desired or needed:


In [30]:
val x = 42

In [31]:
x


Out[31]:
42

In [32]:
val x: Int = 42

In [33]:
x


Out[33]:
42

In [34]:
val x: Double = 42

In [35]:
x


Out[35]:
42.0

Expressions

Emphasizing the functional programming paradigm Scala's syntax has expressions only, but no statements. The former return values and can have side effects, while the latter can only have side effects.

Blocks

Unlike in Python, blocks in Scala are expressions, too, and have a return value defined by the last expression inside the block (this is also why there is no return statement needed in Scala):


In [36]:
{
  var x = 42
  var y = 23
  x + y
}


Out[36]:
65

Basic Datatypes

Scala has limited support for basic datatypes that it can express as literals. These are Booleans, numbers, strings, symbols, tuples, but also XML and functions. Other types like lists, sets or maps (dictionaries in Python) need to be created using their respective names (or are the result of other operations or methods), see section Additional Basic Datatypes below.

Booleans


In [37]:
true


Out[37]:
true

In [38]:
false


Out[38]:
false

Scala's logical operations on Booleans are the usual suspects as known from C/C++/Java:


In [39]:
true || false


Out[39]:
true

In [40]:
true && false


Out[40]:
false

In [41]:
! true


Out[41]:
false

In [42]:
true == false


Out[42]:
false

In [43]:
true != false


Out[43]:
true

In [44]:
true > false // plus <, >=, <=


Out[44]:
true

Numbers


In [45]:
42


Out[45]:
42

In [46]:
42f


Out[46]:
42.0

In [47]:
42d


Out[47]:
42.0

In [48]:
3.14


Out[48]:
3.14

In [49]:
3.


Out[49]:
Name: Syntax Error.
Message: 
StackTrace: 

Strings


In [50]:
"ABC"


Out[50]:
ABC

In [51]:
// single characters
'A'


Out[51]:
A

In [52]:
"Missisippi".distinct


Out[52]:
Misp

Tuples


In [53]:
(0, 1, 2)


Out[53]:
(0,1,2)

In [54]:
// tuple unpacking
var (x, y, z) = (0, 1, 2)

In [55]:
(x, y, z)


Out[55]:
(0,1,2)

Ranges


In [56]:
0 to 5


Out[56]:
Range(0, 1, 2, 3, 4, 5)

XML

On these XML objects you can perform search, filter and all kind of things. You can also blend XML and Scala code directly in the language e.g. in order to create XML code dynamically from Scala objects. In Python one would use templating and XML processing packages like jinja2 and libxml. This feature is beyond the scope of this notebook, though. See the References section for more information.

String Interpolation

Scala has a conveniant string formatting mechanism, which in Python 3.6 is called Literal String Interpolation, with a similar syntax, but with f as a string prefix and curly braces for denoting the references to other variables.


In [57]:
val name = "Alice"
val age = 11
val str = s"$name is $age years old."

In [58]:
str


Out[58]:
Alice is 11 years old.

Specific formatting details can be expressed with printf-like format strings like %s, but prefixing the entire string with an f instead of s:


In [59]:
val name = "Alice"
val age = 11
val str = f"$name%s is $age%d years old."

In [60]:
str


Out[60]:
Alice is 11 years old.

There is also a raw interpolator that performs no escaping of literals within the string, similar to raw strings in Python with prefix r:


In [61]:
raw"a\nb"


Out[61]:
a\nb

In [62]:
"a\nb"

Package Imports

In Scala many datatypes are accessible only by using their textual names and/or after importing them from its standard library.


In [63]:
// wildcard import
import scala.collection._
// selective import
import scala.collection.immutable.Vector
import scala.collection.{Seq, Map}
// renaming import
import scala.collection.immutable.{Vector => Vec28}
//// import all from java.util except Date
// import java.util.{Date => _, _}
// declare a package
package pkg at start of file
package pkg { ... }
// specify package root to avoid collisions
import _root_.scala.math._


Out[63]:
Name: Compile Error
Message: <console>:4: error: illegal start of definition
package pkg at start of file
^
StackTrace: 

Additional Basic Datatypes

List, Array, Vector

Lists are immutable (Arrays are mutable).


In [64]:
var xs = List(0, 1, 2)

In [65]:
xs


Out[65]:
List(0, 1, 2)

In [66]:
xs(1)


Out[66]:
1

In [67]:
// concatenate
1 :: List(2, 3)


Out[67]:
List(1, 2, 3)

Set


In [68]:
// import scala.collection.Set
var s = Set(0, 1, 2)

In [69]:
s


Out[69]:
Set(0, 1, 2)

In [70]:
s += 3

In [71]:
s -= 2

In [72]:
s


Out[72]:
Set(0, 1, 3)

In [73]:
s.contains(0)


Out[73]:
true

Map

These are what is called dictionaries in Python:


In [74]:
Map('a' -> 1, 'b' -> 2) // scala.collection.immutable.Map[Char,Int] = Map(a -> 1, b -> 2)


Out[74]:
Map(a -> 1, b -> 2)

In [75]:
Map('a' -> 1, 'b' -> 2, 9 -> 'y') // scala.collection.immutable.Map[AnyVal,AnyVal] = Map(a -> 1, b -> 2, 9 -> y)


Out[75]:
Map(a -> 1, b -> 2, 9 -> y)

BigInt


In [76]:
import scala.math.BigInt

In [77]:
val x = BigInt(1024)

In [78]:
x * x * x * x * x


Out[78]:
1125899906842624

BigDecimal

Scala's BigDecimal type corresponds to Python's decimals.Decimal class... precission... Big??


In [79]:
val amount = BigDecimal(12345670000000000000000000.89)

In [80]:
print(amount * amount)


1.524155677489E+50

Complex Numbers

Complex numbers seem to be, well, lacking from Scala's (and Java's) standard library, unlike in Python which has also literals for them, like 2+3j. This is maybe a reason why in Scala tutorials it is so popular to give sample implementations for complex numbers.

Conditions

In Scala conditions are also expressions which makes them much more nicely composable than the conditional statement in Python.


In [81]:
var one = 1
var two = 2
var ten = 10

In [82]:
if (one < two) "right"


Out[82]:
right

In [83]:
if (one > two) "right" else "wrong"


Out[83]:
wrong

In [84]:
if (one > two) "right"


Out[84]:
()

These Scala if statements above return the result of the branch that evaluates as true, unlike in Python, where these statements cannot return a result. But in Scala one can write very short assignments based on a conditional expressions:


In [85]:
var result = if (one > two) "right" else "wrong"

The equivalent in Python goes like this: result = "right" if (one > two) else "wrong".

Unlike Python, Scala does not accept multiple Boolean operators in one expression:


In [86]:
if (one < two < ten) "right" else "wrong"


Out[86]:
Name: Compile Error
Message: <console>:31: error: type mismatch;
 found   : Int
 required: Boolean
       if (one < two < ten) "right" else "wrong"
                       ^
StackTrace: 

In [87]:
if (one < two < ten)
  "right"
else
  "wrong"


Out[87]:
Name: Compile Error
Message: <console>:31: error: type mismatch;
 found   : Int
 required: Boolean
       if (one < two < ten)
                       ^
StackTrace: 

Scala's syntax for multi-branch if statements is a little bit cumbersome for people used to Python's if-elif-else:


In [88]:
val x = ten
if (x == one){
  println("Value of X is 1");
} else if (x == two){
  println("Value of X is 2");
} else{
  println("This is the else statement");
}


This is the else statement

The advantage is that one can put an entire such statement on a single line (shortened here slightly):


In [89]:
val x = ten
if (x == one) 1 else if (x == two) 2 else "something else"


Out[89]:
something else

Since conditions are expressions, too, one can store them away and use them at a later time (something that in Python only works by replacing the condition with the result of a function to be called):


In [90]:
val cond = one < two
if (cond) "right"


Out[90]:
right

Loops

"generators", "guards", "yield" returns a vector


In [91]:
for (i <- 0 to 9) println(i)


0
1
2
3
4
5
6
7
8
9

In [92]:
var count = 5
while (count >= 0) { println(s"Counting... $count"); count -= 1 }


Counting... 5
Counting... 4
Counting... 3
Counting... 2
Counting... 1
Counting... 0

The break and continue statements (for breaking out of and for continuing a loop) as known from Python do not exist in Scala, at least not as statements. Instead one can import a similar functionality based on exceptions:


In [4]:
import util.control.Breaks._

After importing this package's content there is a break function (or method?) that can be used like a statement (while it actually raises an exception):


In [13]:
for (i <- Range(1, 10)) { 
  if (i > 3) break
  println(i)
}


1
2
3
Out[13]:
Name: scala.util.control.BreakControl
Message: null
StackTrace: 

A continue functionality is even more cumbersome and involves catching a break with breakable... More to come...

Exceptions


In [93]:
throw new Exception("RTFM")


Out[93]:
Name: java.lang.Exception
Message: RTFM
StackTrace: 

In [94]:
try {
  1 / 0
} catch {
  case e: Exception => println("exception caught: " + e)
}


exception caught: java.lang.ArithmeticException: / by zero
Out[94]:
()

In [95]:
try {throw new Exception("RTFM") } catch { case e: Exception => println("exception caught: " + e)}


exception caught: java.lang.Exception: RTFM

In [96]:
try {
  throw new Exception("RTFM")
} catch {
  case e: Exception => println("exception caught: " + e)
}


exception caught: java.lang.Exception: RTFM

In [97]:
// try {throw new Exception("RTFM")}
catch {case e: Exception => println("exception caught: " + e)}


Out[97]:
Name: Unknown Error
Message: <console>:2: error: illegal start of definition
catch {case e: Exception => println("exception caught: " + e)}
^
StackTrace: 

Functions


In [98]:
def sqr(x: Int) = x * x

In [99]:
sqr(2)


Out[99]:
4

In [100]:
def sqr(x: Int) = { x * x }

In [101]:
sqr(2)


Out[101]:
4

Scala distinguished between functions with parameters and functions without. Those without parameters can be called in Scala without parantheses, unlike in Python, where empty parantheses are mandatory:


In [102]:
def foo() = "bar"

In [103]:
foo


Out[103]:
bar

In [104]:
def bar = "foo"

In [105]:
bar


Out[105]:
foo

Named and default parameter values


In [106]:
def decorate(str: String, left: String = "[", right: String = "]") =
    left + str + right

In [107]:
decorate("Hello", right="]<<<")


Out[107]:
[Hello]<<<

Variable argument number


In [108]:
def sum(args: Int*) = {
    var result = 0
    for (a <- args) result += a
    result
}

In [109]:
sum(1, 2, 3, 4, 5)


Out[109]:
15

In [110]:
sum(1 to 5)


Out[110]:
Name: Unknown Error
Message: <console>:33: error: type mismatch;
 found   : scala.collection.immutable.Range.Inclusive
 required: Int
       sum(1 to 5)
             ^
StackTrace: 

In [111]:
sum(1 to 5: _*)


Out[111]:
15

Recursive Function


In [112]:
def fib(n: Int): Int = {
  if (n < 2) n else fib(n - 1) + fib(n - 2)
}

In [113]:
0 to 10 map(fib)


Out[113]:
Vector(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55)

In [114]:
fib(6)


Out[114]:
8

In [115]:
assert(fib(6) == 7, "wrong")


Out[115]:
Name: java.lang.AssertionError
Message: assertion failed: wrong
StackTrace:   at scala.Predef$.assert(Predef.scala:170)

Anonymous Functions

Scala provides anonymous functions like those defined with Python's lambda expression:


In [116]:
(x: Int) => x + 1

In [117]:
for (i <- 0 to 3) yield ((x: Int) => x + 1)(i)


Out[117]:
Vector(1, 2, 3, 4)

In [118]:
val succ = (x: Int) => x + 1

In [119]:
succ(42)


Out[119]:
43

Built-in Functions

  • no equivalent for Python's id() function

In [120]:
/* for Python 3.6:
   abs, all, any, ascii, bin, callable, chr, compile, delattr, dir, divmod, eval, exec,
   format, getattr, globals, hasattr, hash, hex, id, input, isinstance, issubclass, 
   iter, len, locals, max, min, next, oct, ord, pow, print, repr, round, setattr, sorted,
   sum, vars, open */


Out[120]:
Name: Syntax Error.
Message: 
StackTrace: 

In [121]:
// abs chr divmod has hex len max min oct ord pow round sorted sum


Out[121]:
Name: Syntax Error.
Message: 
StackTrace: 

Annotations

Along the lines of Python decorators, but rather less powerful...

Classes

The simplest class possible (even shorter than in Python due to the lack of an equivalent to pass):


In [122]:
class C
val c = new C

In [123]:
c


Out[123]:
C@147dca88

In [124]:
println(c)


$line269.$read$$iw$$iw$C@147dca88

Now adding a class body, executed when an object of this class is created (the block is needed even when the body contains only one expression):


In [125]:
class C {
  println("A new C object is born!")
}
val c = new C


A new C object is born!

Of course, classes can have methods, too:


In [126]:
class C {
  def isReady(): Boolean = true // no curly braces needed here 
}
val c = new C
println(c.isReady)


true

Parameters passed to the constructor become public instance variables, unless they are declared private. Notice the absence of a class body:


In [127]:
class C(val pub: Int, priv: Int = 0) // same as: private val priv... 
val c = new C(pub = 1)
println(c.pub)
println(c.priv)


1
Out[127]:
Name: Unknown Error
Message: <console>:28: error: value priv is not a member of C
       println(c.priv)
                 ^
StackTrace: 

In [128]:
c.isHappy


Out[128]:
Name: Unknown Error
Message: <console>:28: error: value isHappy is not a member of C
       c.isHappy
         ^
StackTrace: 

Obtaining Type Information

In the Scala REPL one can use the :type command to find out about the type of an object.

$ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.

scala> :type 42
Int

At run-time one can use the .getClass method. See a few examples below:


In [129]:
"ABC".getClass


Out[129]:
class java.lang.String

In [130]:
'A'.getClass


Out[130]:
char

In [131]:
42.getClass


Out[131]:
int

In [132]:
(40 + 2).getClass


Out[132]:
int

In [133]:
(5 until 9).getClass


Out[133]:
class scala.collection.immutable.Range

Little Pitfalls

These are a few potentially unexpected situations you might run into as somebody exposed for some time to a Python habitat.

Scala and Python differ when applying type inference or coercion rules. This is fine for Scala, but would raise a TypeError in Python:


In [134]:
3.14 + "cool"


Out[134]:
3.14cool

In [135]:
(3.14 + "cool").getClass


Out[135]:
class java.lang.String

And the following is fine for Python, but makes no sense for Scala:


In [136]:
3 * "cool"


Out[136]:
Name: Unknown Error
Message: <console>:25: error: overloaded method value * with alternatives:
  (x: Double)Double <and>
  (x: Float)Float <and>
  (x: Long)Long <and>
  (x: Int)Int <and>
  (x: Char)Int <and>
  (x: Short)Int <and>
  (x: Byte)Int
 cannot be applied to (String)
       3 * "cool"
         ^
StackTrace: 

Concatenation


In [137]:
"A" + "B" + "C"


Out[137]:
ABC

In [138]:
'A' + 'B' + 'C'


Out[138]:
198

In [139]:
'Æ'.toInt


Out[139]:
198

In [140]:
'A'.toInt


Out[140]:
65

In [141]:
"ABC".sum


Out[141]:
Æ

For some operators there is no literal infix notation like the ** exponentiation operator in Python. Here one needs to use imported functions like scala.math.pow() in this case (which is also available in Python as math.pow):


In [142]:
scala.math.pow(2, 3)


Out[142]:
8.0

In Scala there is often more than "one way to do it", a feature that Python claims for itself, with a few notable exceptions, though):


In [143]:
6 * 7


Out[143]:
42

In [144]:
42.0


Out[144]:
42.0

In [145]:
42f


Out[145]:
42.0

In [146]:
42d


Out[146]:
42.0

In [147]:
6. * 7


Out[147]:
Name: Unknown Error
Message: <console>:1: error: ';' expected but integer literal found.
6. * 7
     ^
StackTrace: 

In [148]:
6 * 7.


Out[148]:
Name: Syntax Error.
Message: 
StackTrace: 

In [149]:
6. * (7)


Out[149]:
42

In [150]:
6.*(7) // * is actually a method!


Out[150]:
42

In [151]:
6.*(7+0)


Out[151]:
42

In [1]:
Array.range(1, 11)


Out[1]:
Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

In [152]:
Range(1, 11)


Out[152]:
Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

In [153]:
1 until 11


Out[153]:
Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

In [154]:
1 to 10


Out[154]:
Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

In [155]:
1.to(10)


Out[155]:
Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

In [156]:
import scala.language.postfixOps // enable postfix operators
1 to 10 map(sqr) sum


Out[156]:
385

In [157]:
sqr(1 to 10 sum)


Out[157]:
3025

In [158]:
1 to 10 sum sqr


Out[158]:
Name: Unknown Error
Message: <console>:32: error: missing argument list for method sqr
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `sqr _` or `sqr(_)` instead of `sqr`.
       1 to 10 sum sqr
                   ^
StackTrace: 

In [159]:
{}.getClass


Out[159]:
void

In Scala you can try to execute something, without any attempt to catch errors. This means trying something is identical to doing it:


In [160]:
try {print(42)}


42

In [161]:
print(42)


42

In [162]:
var v = try {1} finally {2}

In [163]:
v


Out[163]:
1

One could sometimes argue if some methods return what one would expect. The String.distinct method e.g. returns a string with characters in the same order as in the input string, while one could also expect an array (or even a set) as returned by String.split():


In [164]:
"Missisippi".split("")


Out[164]:
Array(M, i, s, s, i, s, i, p, p, i)

In [165]:
"Missisippi".distinct


Out[165]:
Misp

In [166]:
"Missisippi".distinct.getClass


Out[166]:
class java.lang.String

Comparison

Similarities between Python and Scala:

  • high code expressiveness
  • use of semicolons at the end of lines is optional
  • whitespace is relevant(?)
  • similar exception handling
  • usage of tripple-quotes for multi-line strings
  • mix of imperative, object-oriented and functional programming paradigms
  • Scala's type declarations seem very similar to those of Python 3 which can be statically checked using MyPy

Differences (Scala-centric):

  • Scala uses curly braces for blocks (and therefore needs no "empty" statement like Python's pass)
  • Scala recommends two blanks for indented code while Python recommends four
  • Scala's style guidelines emphasize camel case more often than Python's
  • Scala offers fewer datatypes available as literals
  • Scala allows no multiple operators in Boolean expressions
  • Scala sports more numeric types: Int, Float, Double, BigInt, BigDecimal
  • Scala doesn't follow Python's "only one way to do it" philosophy
  • Scala appears to have a cleaner top-level namespace (Python's contains e.g. built-in functions like abs, divmod, max, min, pow, round, and sum which are clearly math-related)
  • Scala offers access to everything JVM, Python does only via Jython which seems to have stalled in development
  • Scala's standard library is much smaller, e.g.:
    • no complex numbers (seem to be missing in Java, too)
    • no JSON support, see http://json4s.org
  • Scala continues the C/Java tradition of using logical operators (!, &&, etc.) which appear less readable/friendly than Python's named operators (not, and, etc.)
  • Scala's implementation for breaking and especially continuing loops is way more cumbersome than Python's
  • Scala implements inconsistent indexing schemes for different datatypes like tuples, lists and strings

Conclusions

  • Scala is certainly a great improvement over Java
  • it adds a widely accepted/needed functional programming style
  • its syntax is both, more compact and expressive, than Java's
  • it has a rich standard library regarding collection classes
  • it has a poor standard library support for any wider set of applications
  • it has syntax features of questionable, if any, value

Appendix: Local Installation

This is an attempt to describe a local installation of several components needed to run Jupyter with the Apache Toree Scala kernel on a local computer. As some of these components can be installed in various ways the following gives only one example and only for OS X (after installing brew first!):

brew install python
pip install jupyter
brew install apache-spark
pip install https://dist.apache.org/repos/dist/dev/incubator/toree/0.2.0/snapshots/dev1/toree-pip/toree-0.2.0.dev1.tar.gz
jupyter toree install —spark_home=/usr/local/Cellar/apache-spark/2.1.0/libexec
jupyter notebook

TODO

  • Types: Array, List, Map
  • introspection
  • documentation
  • testing
  • more details on functions and classes
  • Null, Nil, Void
  • iterators
  • comprehensions
  • context managers?
  • warnings?
  • logging?