// hello world in Scala
object helloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
defined object helloWorld
Thadryan
July 20, 2018
Scala is a JVM language that seeks to marry functional and object-oriented programming styles. It was was Designed by Martin Odersky and first appeared in 2004. While I think many projects that aspire to “best of both worlds” status end up ugly and chimeric, my explorations with Scala have revealed a really thoughtful and lovely creation that elegantly merges different paradigms. While it isn’t one of the top-tier languages for for production code job hunting (think Java, C++, Python, JavaScript, etc), it made the GitHub top 15 list for most common languages recently. I suspect much of this is because it’s becoming popular as a language for data science as a happy medium language between the breezy-to-write-but-relatively-slow Python and the incumbent production veteran Java that is faster but comes with a notoriously verbose syntax (still very much worth learning though!). Scala aims to be approachable and quick to develop as well as fast (some tests show it performing at Java speed or better), thus avoiding the need to “productionize” slower, exploratory code if a project grows (The name “Scala” is a shortening of the “Scalable Language”, after all). Nobody is going to be putting Java out of business any time soon (just ask the flashier start-up favorite Ruby, but Scala joins Python, Java, and R as a helpful tool for data and general purpose coding. After spending a good amount of time with the Scala home page, “Scala for the Impatient”by Cay S. Horstmann, and Bruce Eckel’s classic “Thinking in Java”, I opted to create an overview for my own edification and for some people I know who are newcomers to the language. Happy Hacking.
// hello world in Scala
object helloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
defined object helloWorld
In Scala, a program takes place in a “singleton object”. This is an object of which only one iteration can exist. This is slightly different than Java, where it would be written as “class helloWorld {”.
Next we see a “main” method defined like in Java. Also like Java, this function takes an Array of Strings as an argument ( args: Array[String]) ). The more unusual part is “Unit”. This is the Scala’s version of “void”, which means that the function doesn’t return anything (it just executes the code inside it).
After that, there is a println() call that will look familiar to Java coders that prints the message.
Because we are using a notebook, we can write snippets of code outside an object like this, but keep in mind if we were writing a program in a more typical format it would need to be inside that object.
From now on, we can just write:
In Scala, variables are declared as “Val” or “Var”, for “Value” or “Variable”. A item declared as a “Val” cannot be changed (it is said to be “immutable”, where as a “Var” can (it is “mutable”). This a key part of Scala’s functional programming background.
This means we could change x but we could not change y:
// this is perfectly legal
x = x + 1
println(x)
// this would kick a "reassignment to val" error
// y = y + 1
2
The next line of code demonstrates that Scala’s type declarations are “backwards” compared to more traditional languages. Scala would say “val age: Int = 10” not “Int age = 10”. According to Cay S. Horstmann, the author or “Scala for the Impatient”, this makes it easier to read the code when large, complicated functions are used. While this isn’t typical, Scala’s designers aren’t the only ones who think so:
https://blog.golang.org/gos-declaration-syntax
It takes a bit of getting used to but is not a huge deal, and the clarity pays off later. I think of this as the programming equivalent of Romance languages that say “The dress red” instead of “The red dress”.
nameDeclared: String = "Charli Declared"
Also, Scala has type inference, so we could use this shorthand:
Given it’s descent from Java and it’s intent to build large systems securely, Scala uses strong, static typing.
val wholeNumber: Int = 10
val decimalNumber: Double = 10.1
// specify float
val floatDecimalNumber: Float = 10.1f
val bigNumber: Long = 100000000
// note double quotes
val string: String = "Heya"
// note single quotes
val aLetter: Char = 'A'
val answer: Boolean = true
// will be convere
val doubleOverridesInt = wholeNumber + decimalNumber
wholeNumber: Int = 10 decimalNumber: Double = 10.1 floatDecimalNumber: Float = 10.1F bigNumber: Long = 100000000L string: String = "Heya" aLetter: Char = 'A' answer: Boolean = true doubleOverridesInt: Double = 20.1
Scala types are built as classes, so it offers some convenience methods for conversion:
Arithmetic operators are fairly traditional in Scala:
Exponents are handled via Scala’s math library.
Let’s look at some simple string manipulations.
Note that the () is used, not the traditional []. This is due to Scala’s functional outlook, looking at the String as a function that maps an element to the String location of that element.
Let’s change the case. Notice there are no () at the end of this method calls. If the method has parenthesis, they are optional if arguments are not being passed (if the method is declared with no parenthesis, however, you must follow suit).
res63_0: String = "JADE" res63_1: String = "jade"
Iterating over a string reveals some interesting traits of Scala. The String class has a “foreach” method, which, paired with the “default variable” and a bit of syntax, allows for iteration.
We can also use and index. It has an R-like arrow assignment to the i, and then an obvious, English-like syntax for “0 until the end of the length” of the name.
// for i in until the end of the length
for(i <- 0 until name.length) {
println("Letter at index " + i + " is " + name(i))
}
Letter at index 0 is J
Letter at index 1 is a
Letter at index 2 is d
Letter at index 3 is e
We can also use and index. It has an R-like arrow assignment to the i, and then an obvious, English-like syntax for “0 until the end of the length” of the name.
In Scala 2.1+ you can interpolate strings with the s + $ syntax
This also works with floats, using a C-style syntax specifying the number of decimals:
Scala arrays are traditional in tha they are static; once you declare one to be a certain length, it can’t be changed. Interestingly, the individual elements of the array can be change:
// declare and array - this uses type inference
val numbers = Array(2,4,6,8,10)
// could also be
// val numbers: Array[Int] = Array(2,4,6,8,10)
// access it by index (starting at 0)
println(numbers(4))
// it also has the foreach method
numbers.foreach { number =>
println(number)
}
// update by index
numbers(1) = 2
10
2
4
6
8
10
numbers: Array[Int] = Array(2, 2, 6, 8, 10)
The Array class has the basic methods you might expect:
Given Scala’s functional heritage, it’s common to see map function used to transform data structures.
// declare an array
val numbers: Array[Int] = Array(3,6,9,12,15)
// map each "x" in the list to "x * 2"
val doubledNumbers = numbers.map(x => x * 2)
numbers: Array[Int] = Array(3, 6, 9, 12, 15) doubledNumbers: Array[Int] = Array(6, 12, 18, 24, 30)
You might be wondering if we can add conditionals to this basic idea to get generators or comprehensions. You bet, using yield.
What about a dynamic array? Scala’s standard library provides a Java-like ArrayBuffer:
// import the data structure
import scala.collection.mutable.ArrayBuffer
// declare one, empty
val dynamic = ArrayBuffer[Int]()
println(dynamic.length)
// note handy "by" option letting us count by "2"
for(i <- 2 to 10 by 2) {
dynamic += i
}
println(dynamic.length)
0
5
import scala.collection.mutable.ArrayBuffer // declare one, empty dynamic: ArrayBuffer[Int] = ArrayBuffer(2, 4, 6, 8, 10)
Generally speaking, Scala is very syntactically consistent; the basic methods have the same names as the regular array:
The control flow in Scala is traditional and straightforward, strongly resembling and C-family language. The comparison operators will also seem familiar.
val numbers = Array(1,2,3,4,5,6,7,8,9,10)
numbers.foreach{ number =>
// check for even/odd with "=="
if(number % 2 == 0){
println("The number is even")
}
// scala uses ! for negative comparisons
else if(number % 2 != 0){
println("The number is odd")
}
// final condition, not activated here
else{
println("Does not compute!")
}
}
The number is odd
The number is even
The number is odd
The number is even
The number is odd
The number is even
The number is odd
The number is even
The number is odd
The number is even
numbers: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
A simple function in Scala looks a bit like lambda expressions in other languages and can be defined like this:
addTwoNumbers: (Int, Int) => Int = ammonite.$sess.cmd76$Helper$$Lambda$2850/0x0000000800905a78@2ea8ff5a res76_1: Int = 9
Using def is for making a method (in this case of the main object)
Scala uses a Python-like default arguments to avoid method overloading (we use () because there is an arguments list in this function):
// Simply add ' = "Bonnie"' and you're good to go
def introduceYourself(name: String = "Bonnie"): Unit = {
println(s"Hello there, my name is $name")
}
introduceYourself() // defaults to Bonnie
introduceYourself("NotBonnie") // uses input we specify
Hello there, my name is Bonnie
Hello there, my name is NotBonnie
defined function introduceYourself
// store keys and values
var stars = Map("Lee" -> "Pace", "Kerry" -> "Bishe'", "MaKenzie" -> "Davis")
// or
// Map[String, String] = Map("Lee" -> "Pace", "Kerry" -> "Bishe'", "MaKenzie" -> "Davis")
println(stars("Lee"))
Pace
stars: Map[String, String] = Map(
"Lee" -> "Pace",
"Kerry" -> "Bishe'",
"MaKenzie" -> "Davis"
)
It is easy to add new entries:
// the += syntax carries over
stars += ("Scoot" -> "McNairy")
stars += ("Toby" -> "Huss")
// using keys yields and array which also has "foreach"
stars.keys.foreach{ actor =>
println(actor + " " + stars(actor))
}
Scoot McNairy
Kerry Bishe'
MaKenzie Davis
Toby Huss
Lee Pace
There is also a “values” method:
It’s also simple to reverse a mapped/paired structure using mapping:
We’ve mostly seen simple imperative programming and hints of Scala’s functional origin but it also an Object Oriented language.
The most simple version of OO Scala is the case class. While a bit foreign to Java folks, they are quite handy. Case classes are generally small, simple, immutable structures, like points on a graph. Let’s define one:
That’s it. It’s disarmingly simple compared to a Java object, but it works. Part of this is because it assumes that you want immutable fields unless otherwise specified (part of the functional meets OO approach). Creating one is straightforward and largely familiar to Java folks:
// make a new Point
val myLocation = new Point(1,2)
// access the members
myLocation.x
myLocation.y
//// can't do this:
// myLocation.x = 5
//// unless it was defined like this, specifying they could vary
// case class Point(var x:Int, var y:Int)
myLocation: Point = Point(1, 2) res84_1: Int = 1 res84_2: Int = 2
We will make a simple Person class that has a private value (available only to the class) to represent its age and a String for a name. We will include methods for it to get older and to display the current age. Classes are public by default.
// define a class
class Person {
// set a field
private var age = 0
var name = ""
// method to increase age
def getOlder { age += 1 }
// method to say age
def sayAge { println(age) }
}
// make a new instance
val rando = new Person
// show age before and after method call
rando.sayAge
rando.getOlder
rando.sayAge
// give the person a name
rando.name = "Abakus"
println(rando.name)
0
1
Abakus
defined class Person rando: Person = ammonite.$sess.cmd85$Helper$Person@6162ffa6
What if we wanted to make mandatory fields? We can include them in the parenthesis in a move that will look familiar to Python coders.
// define a person with a name and an age
class Person(val name: String, var age: Int)
//// this would crash "not enough arguments for constructor":
//> val kanye = new Person(name = "Kanye")
///...because it doesn't have the arguments that we told it were needed.
// make a new instance of the class named kanye
val kanye = new Person(name = "Kanye", age = 35)
// show values
kanye.name
kanye.age
defined class Person kanye: Person = ammonite.$sess.cmd86$Helper$Person@360cbb22 res86_2: String = "Kanye" res86_3: Int = 35
Constructors allow the writer to dictate behavior that takes place whenever an instance of the class is created (for the uninitiated, the footnotes of this page contain a brief explanation). It’s common, for instance, for an object that reads a file to do so upon to construction. This saves the time of creating the object and then calling a method to have it read the file. In C++ and Java, the constructor is a method of the class that has the same name as the class. In Scala however, it just executes the code immediately inside the class definition. Let’s take a look at a simple example:
class TinyHuman {
// this is constructor behavior
println("I have been born and am alive!")
}
// this will print it's greeting even thought we didn't call anything
val newborn = new TinyHuman
I have been born and am alive!
defined class TinyHuman newborn: TinyHuman = ammonite.$sess.cmd87$Helper$TinyHuman@7e1bdf48
Getters and Setters are built into classes by Scala (for the unfamiliar, the footnotes of this page contain a brief explanation). While this might seem wild, the programmer can control them using “var”, “val”, and the “private” keyword to restrict how they are used, allowing full control of the class. The auto-generator methods are “foo” and “foo_” in the Java Virtual Machine code made by compiling Scala.
class Year {
var month = 1 // starts in Jan
}
val thisYear = new Year()
thisYear.month // this will call the internal "foo", in this case, "month"
thisYear.month = 2 // this calls the "foo_", in this case "month_"
defined class Year thisYear: Year = ammonite.$sess.cmd88$Helper$Year@182a8837 res88_2: Int = 1
Scala will also allow you to define “foo” and “foo_” yourself if you want to (or just foo).
To make Scala write only a getter method declare that value with “val”. Because vals cannot change, it will not bother with setter method.
To make Scala create a getter and a setter, declare an attribute with “var” - an attribute that can change will require a getter and a setter.
Private attributes work in a Java-like way. Here, we use private to make an attribute that can be incremented by the user but not set to whatever they want as they can’t access it directly:
Scala generates a standard constructor for all the classes you define.
We can do so using what Scala calls a “Primary Constructor”. This is like a constructor in other languages except that is is implicitly created as part of the class definition.
Scala provides a predictable means of single inheritance (Like Java, Scala does not implement multiple inheritance).
// class and method definition in a single line?
class Kid { def talk(): Unit = { println("I say the damnest things") }}
class PreTeen extends Kid{}
// will automatically have the method from Kid even though it is a preteen
val newKid = new PreTeen
newKid.talk
I say the damnest things
defined class Kid defined class PreTeen newKid: PreTeen = ammonite.$sess.cmd91$Helper$PreTeen@a4d13c1
Java coders: note that Scala constructors do not require the use of super(), though the languages does support it for access superclass methods in general and it is used the same way as in Java.
Scala offers “mixins” for composing classes based on functionality.
// define a lover that loves
trait lover {
def love(): Unit = {
println("I am a lover!")
}
}
// define a fighter that fights
trait fighter {
def fight(): Unit = {
println("I am a fighter!")
}
}
// mix them together to make a rouge
class rouge(name: String) extends lover with fighter {
// the rouge can call both of methods from the mixins
def enGarde(): Unit = {
love
fight
println("I am " + name + "!")
}
}
val zoro = new rouge("Zoro") // make a new rouge
zoro.enGarde // put foes on notice!
I am a lover!
I am a fighter!
I am Zoro!
defined trait lover defined trait fighter defined class rouge zoro: rouge = ammonite.$sess.cmd92$Helper$rouge@22a12e9e
Scala supports the “override” keyword to specify a new method behavior. Let’s make a subspecies of Rouge with his own enGarde() protocol:
class revengeSeeker(name: String, warning: String) extends rouge(name) {
// override the definition of enGarge
override def enGarde(): Unit = {
love
fight
println("I am " + name + " " + warning)
}
}
val inigo = new revengeSeeker(name = "Inigo Montoya", warning = "Prepare to die!")
inigo.enGarde
I am a lover!
I am a fighter!
I am Inigo Montoya Prepare to die!
defined class revengeSeeker inigo: revengeSeeker = ammonite.$sess.cmd93$Helper$revengeSeeker@4b5258dc
What’s a Constructor?
For the unfamiliar, a constructor is a special method that activates when a class is created. They keep the user from having to specify behavior for each object created after it is initialized.
Getters and Setters are worth a discussion in their own right, but for a working knowledge, they are methods to access or change object attributes. They are used when there is a reason to conceal the traits from the end-user. A good example of when to use a Getter would be in a class where a Person class with and “age” attribute that should not be able to get younger (as provided in “Scala for the Impatient”). It’s easy for the programmer of the class to write code to keep the age from running if it doesn’t fit the criteria designated by the Setter.