Luet oppimateriaalin englanninkielistä versiota. Mainitsit kuitenkin taustakyselyssä
osaavasi suomea. Siksi suosittelemme, että käytät suomenkielistä versiota, joka on
testatumpi ja hieman laajempi ja muutenkin mukava.
Suomenkielinen materiaali kyllä esittelee englanninkielisetkin termit. Myös
suomenkielisessä materiaalissa käytetään ohjelmaprojektien koodissa englanninkielisiä
nimiä kurssin alkupään johdantoesimerkkejä lukuunottamatta.
Voit vaihtaa kieltä A+:n valikon yläreunassa olevasta painikkeesta. Tai tästä:
About This Page
Questions Answered: How can I define names for accessing the values
I need in my program? How can I store information in the computer’s
Topics: Variables (val and var). We’ll also revisit and expand
on the topics of the previous chapter.
What Will I Do? Program in the REPL and read.
Rough Estimate of Workload:? An hour or a bit more.
Points Available: A35.
Related Projects: None.
Notes: This chapter makes occasional use of sound, so speakers or
headphones are recommended. They aren’t strictly necessary, though.
What arithmetic expressions would you write to compute the following three things?
One answer is in the REPL interaction below.
6 * 6 * 6res0: Int = 216
1 * 2 * 3 * 4 * 5 * 6res1: Int = 720
That’s two down, no problem. But what about the third expression?
1 * 2 * 3 * 4 * 5 * 6 * 1 * 2 * 3 * 4 * 5 * 6 * 1 * 2 * 3 * 4 * 5 * 6res2: Int = 373248000
That’s pretty unpleasant to write and pretty unpleasant to read. What’s more, the computer
needs to carry out more multiplications than necessary as it executes our command (which
doesn’t have any practical significance in this small example, though).
It would be nice to be able to write: “Compute the factorial, store that intermediate
result, then cube it.” And we can.
Nearly all programs store values in the computer’s memory. By storing values, the
computer can keep track of things that matter during a program run, such as intermediate
results or, say, the ratings and prices entered by a user of the GoodStuff app.
Obviously, once something is stored, we need to be able to access it. The best way to do
that is to define names that refer to the stored information.
For storing values, programmers use variables (muuttuja) ; a variable is a named
location where you can store a single value. Commanding the computer to store a value
in a variable is called assignment (sijoitus):
Here is a better way to solve “cube of factorial of six”.
Let’s first define a variable and store the intermediate result in it.
Here’s how. Again, recall that you can hover your mouse cursor over the
green boxes to see what the explanations connect to.
val factorial = 1 * 2 * 3 * 4 * 5 * 6
Here is how the REPL responds to your defining a variable:
val factorial = 1 * 2 * 3 * 4 * 5 * 6factorial: Int = 720
Now we can use our variable to compute the cube of the factorial:
factorial * factorial * factorialres3: Int = 373248000
Notice that a variable’s name alone is an expression. Its value is the value that’s
stored in the variable. Such a variable name, just like other expressions, can appear
in more complex expressions. In our example, for instance, the variable name appears
(three times) as a subexpression of an arithmetic expression.
The animation below details the execution of the code that we just discussed. Please watch
the animation even if you feel that you understood the example! Pay particular attention
to the order of execution steps. The order of these steps during a program run will be
increasingly important as we encounter increasingly elaborate programs.
1 * 2 * 3 * 4 * 5 * 6
Watch out for familiar math!
In some ways, program code looks like familiar mathematical notation.
But it’s not precisely the same thing, and this similarity has
confounded many beginner programmers.
Consider the assignment command. It’s not an equation, and the two
sides of the equals sign are not interchangeable. An assignment
command instructs the computer to assign the value of the expression
on the right to the memory location named on the left. If you try
something like 1 * 2 * 3 * 4 * 5 * 6 = val factorial, you’ll only
end up with an error message.
1 * 2 * 3 * 4 * 5 * 6 = val factorial
Here are the two programs that we just wrote:
1 * 2 * 3 * 4 * 5 * 6 * 1 * 2 * 3 * 4 * 5 * 6 * 1 * 2 * 3 * 4 * 5 * 6res4: Int = 373248000
val factorial = 1 * 2 * 3 * 4 * 5 * 6
factorial * factorial * factorialres5: Int = 373248000
The second version solves the same problem as the original one-liner but is easier
for a human to read. Another improvement (in principle) is that the computer has a bit
less work to do than in the first program. We have thus just had our first brush with two
criteria of program quality: programming style and efficiency of execution.
At least in principle, we can spot a third improvement in code quality, too. Because we
extracted the factorial into a separate command, our code now has less repetition of the
same expression. Less repetition means that the program is easier to develop and modify:
if you wanted to, say, tweak the program to cube the factorial of seven rather than six,
you would find the second version more amenable, since you’d need to change the code in
only one place rather than three. Not only does that mean less work for you, it also
reduces the chance of making a careless mistake.
Of course, because this example program is so tiny, all these improvements to quality
have little practical significance.
The principle of avoiding repetition goes by the acronym DRY (don’t repeat yourself);
some people refer to breaches of this principle as WETWET (write everything twice
write everything twice). When we write larger programs, it’s essential to keep our code
DRY. At this introductory stage, however, it’s enough to sow a seed of thought: a programmer
needs to consider not only whether a piece of code works but also whether it is of high
You can use different kinds of expressions as you define what should be assigned
to a variable. The simplest kind of expression is the literal, and indeed you can
store the value of a literal in a variable:
val myTest = 100myTest: Int = 100
Get to know variables by programming in the REPL and finding out the answers to
the following easy questions.
You can use a variable name in an expression, so it makes sense that you can
also use one you initialize another variable. First create a variable myTest as
above, then issue this command:
val another = 1 + myTest
What is now the value of the second variable (which we gave the name another)?
A variable name alone constitutes an expression:
What is the value of this expression? (Assume that the variable has been defined as above.)
You can copy the value stored in a variable into another variable:
val third = another
Notice that here, too, assignment happens “from the right of the equals sign to the left”:
the variable on the right-hand side must exist already (or you’ll be error-messaged);
the variable mentioned on the left after the val keyword gets created by this command.
After executing the above commnd, what value is stored in third?
You can also use a variable as you pass parameters to a command. Here’s an
example of a println whose parameter expression involves two variables:
println(myTest - third)
What value does this command print out?
Consider the following command and its execution in the REPL.
val something = third * (myTest + 10)
Which of the following are correct?
(myTest + 10)
All the variables we used above were of type Int and stored integer values, but we can
define variables of different types, too. The easiest way to do so is simply to assign a
differently typed value, such as a Double:
val courseGrade = 9.5courseGrade: Double = 9.5
Or a String:
val name = "Anna"name: String = Anna
val songIntro = "cccedddfeeddc---"songIntro: String = cccedddfeeddc---
Or a Color or a Pic, as in the following exercise.
Let’s define a couple of variables in the REPL and assign values to them:
import o1._import o1._
val sizeOfCircle = 300sizeOfCircle: Int = 300
val colorOfCircle = BluecolorOfCircle: o1.gui.Color = Blue
Now let’s try to display a circle with a diameter and color defined by the two
variables that we just created:
show(pictureOfCircle)<console>:18: error: not found: value pictureOfCircle
We forgot something! The error message informs us that the variable pictureOfCircle,
which we tried to use, is not defined. Indeed it isn’t.
In the field below, write a command that defines a variable called pictureOfCircle
such that the above show command is valid and displays a circle. Use the circle
command from Chapter 1.3 and the two variables sizeOfCircle and colorOfCircle
defined above. Please don’t enter the show command, just the variable definition.
The programmer picks names (or identifiers; tunnus) for the variables in their
program. As should already be apparent, variables in Scala are, by and large, given names
that begin with a lower-case letter. No technical necessity forces us to do so, but this
convention is part of good Scala programming style.
If a variable name comprises multiple words, we use upper-case letters to mark word
borders. Here are a few examples:
This naming convention is called “camelCase”. It’s widespread in Scala and common in
other programming languages, although alternative conventions also exist.
Don’t use spaces in variable names. Numbers are fine, but a name can’t begin with a
number. Beginners would do best to avoid special characters such as + or & entirely;
some of these characters have particular meanings in Scala. Letters with diacritics
(e.g., á or ü) are okay in principle, but since they cause occasional trouble in some
programming environments, you may wish to steer clear of them. Scala’s “magic words”,
such as val, properly termed reserved words (varattu sana), can’t be used as
Characters in upper case are distinct from those in lower case, so when you name your
variable myTest, be sure to always type it the same way. The name mytest won’t access
It’s part of good programming practice to give variables names that describe their
purpose. You will see many examples in this ebook. However, when experimenting on tiny
pieces of code in the REPL, it’s fine to use short, generic names such as number, a,
or myTest, even if they may somewhat obscure the variable’s purpose.
O1’s style guide has a bit more to say about naming. We
recommend that you take a look at the guide at some point during the first weeks of O1,
but it’s not necessary to do that just yet.
If you use the plus operator to combine a string with a number, you get a string that
contains the characters that describe the numerical value. Like this:
"kit" + 10res6: String = kit10
val report = "grade: " + courseGradereport: String = grade: 9.5
println(name + ", " + report)Anna, grade: 9.5
Return your thoughts to o1.play, the command introduced in Chapter 1.3, and the song
Ukko Nooa (“Uncle Noah”). Let’s use variables to form a slightly longer string that
covers the entire song. In Ukko Nooa, the bit at the beginning repeats at the end.
This effect is easy to achieve:
import o1._import o1._
val beginning = "cccedddfeeddc---"intro: String = cccedddfeeddc---
val middlePart = "eeeeg-f-ddddf-e-"middlePart: String = eeeeg-f-ddddf-e-
val wholeSong = beginning + middlePart + beginningwholeSong: String = cccedddfeeddc---eeeeg-f-ddddf-e-cccedddfeeddc---
Now let’s see how we can play this song at two different tempos (speeds). Let’s begin
by storing the tempos that we intend to use in descriptively named variables:
val normalTempo = 120normalTempo: Int = 120
val slowTempo = 60slowTempo: Int = 60
The play command can play melodies at different speeds. If you want
something other than the default tempo, you need to give play a string that
contains the melody followed by a slash followed by the tempo. Such as this one:
wholeSong + "/" + normalTempores7: String = cccedddfeeddc---eeeeg-f-ddddf-e-cccedddfeeddc---/120
Here are a couple more examples for you to try:
play(wholeSong + "/" + normalTempo)play(wholeSong + "/" + slowTempo)
Certainly, you’re not obliged to use variables. You can simply write the desired tempo
into a string literal, as below.
Let’s play Ukko Nooa really fast: at double the normal tempo. And let’s make
the computer figure out how much that double speed is.
play(wholeSong + "/" + normalTempo + normalTempo)
But it doesn’t work! Find out what’s wrong and select all the correct claims among
the following options. You can find the solution to each item by experimenting in
the REPL and paying attention to both the actual values you get and their data types.
You can also try printing strings instead of playing them.
println("2 + 2" + 3 + 3)
2 + 233
println(2 + 2 + "3 + 3")
223 + 3
normalTempo + normalTempo
Programs routinely keep track of changing information. For instance, a game might have a
character whose coordinates change as the player moves the character, or the favorite
hotel of a GoodStuff user might change as the user records new experiences.
One way to deal with such needs is to store of the changing information in a variable
and replace the value of the variable with another as needed.
Sounds pretty good, but it turns out that we can’t do that using variables defined with
the val keyword. The value of a val variable is “locked” into the variable and can’t be
replaced with another.
In Scala, we can use the word var as an alternative to val when we create a variable.
A var variable is assigned a value just like a val variable is. The only, but very
significant, difference between the two is that a var lets us replace the stored value
with a new one later on.
Take a close look at the following animation.
In this example, the values of both variables number and doubleThat were eventually
replaced with new ones. This was possible because we defined them with var. If you
were to exchange the vars for vals, the above code would fail to work and produce the
message “error: reassignment to val”.
A potentially confusing feature of the REPL
The REPL lets you define a variable that has the same name as one
you had previously defined: simply write a new var or val
definition. If you do this, you might get the impression that you
can change the value of a val variable. But in reality, what
you’re doing is discarding the old variable and making an entirely
new one in its stead (perhaps even with a different data type).
This is a feature specific to the REPL. In Scala programs outside
the REPL, you cannot enter consecutive commands to create namesake
variables in this way. So forget about this, at least until you’re
fluent with variables.
When you replace the value of a var, you can make use of the variable’s old value as
you specify the new one:
Watch out for math! (again)
Notice and remember: In mathematics, a variable is a symbol that
corresponds to a value. In programming (of the sort that we do
here), a variable is a named location in memory capable of storing
a single value.
In practice, the difference is particularly significant when it
comes to var variables. A program is not a group of equations!
The same program can very well contain, say, the instructions
number = 10 and number = 5. Even number = number + 10 is
valid, despite looking very suspicious through the familiar lens
of math. And the order in which a sequence of commands assigns
values to variables can make a lot of difference!
number = 10
number = 5
number = number + 10
Objection! Why would I ever use val? Doesn’t var let me do all the same stuff and
var variables do present certain additional opportunities, but that isn’t just a good
Programmers constantly reason about how their code works as they write it and as they
try to locate errors in it. This reasoning can be much easier if the programmer knows
that certain things in the code are unchangable. As a simple example, the word val
tells the programmer that the variable’s value will never, ever change no matter
what else happens during the program run. Such matters will grow in significance as
you encounter larger and more complex programs; no doubt you will notice the benefits
of vals already during this introductory course.
In small REPL experiments, it doesn’t much matter which kind of variables you use, but
here is a rule of thumb for all future programming tasks outside the REPL:
Make every variable a val, unless you have
a good reason right now to make it a var.
Don’t make your variables vars “just in case I need to change the value”. That is a
poor programming practice. If it turns out later that a val really isn’t appropriate
for what you’re trying to achieve, you can modify your program to use a var instead.
How is a val even a “variable”?
One may think that, in a sense, only vars are proper variables,
since their value can vary. However, a val can quite reasonably
also be called a variable. For one thing, it can receive different
values during different program runs (e.g., from user input). For
another thing, it’s possible for the same val definition to be
executed multiple times during a program run, so that each execution
creates a separate val with a different value. You’ll see examples
of both things later on.
The mathematical concept of variable is also closer to val
variables than to var variables. In fact, it’s been suggested that
it’s only vals that are variables in the true sense while vars
would be better called “assignables”. But we’ll leave this war of
Functional programming (funktionaalinen ohjelmointi) is
one of the major varieties, or paradigms, of
programming. In its purest form, functional programming uses only
vals. We’ll discuss that in Chapter 10.2.
Student question: In terms of memory use or efficiency, does it make a difference if I pick val or var?
Taken in isolation, there’s no difference between the two
in this respect. The amount of memory reserved for a variable
depends only on the variable’s data type; we’ll discuss that
in Chapter 5.2.
In practice, the matter is more complicated. Among other things,
The choice between var and val affects the optimizations
that compilers (Chapter 5.2) apply as they translate the Scala
code written by a programmer into a more readily executable form.
Also noteworthy is the fact that vals help us write programs
whose parts can be run efficiently in parallel by multiple
computers or processor cores. Parallel execution is not a theme
that we’ll be exploring further in O1, however.
What is the output of this piece of code?
var example = 2
example = example * example
example = example * example
println(example * example)
Enter your answer here:
Here is another example that features strings:
var word = "camel"
word = word + "opard"
word = "ant"
word = "gr" + word
word = "fra" + word
What is the value of the variable word after the last line has been executed?
In addition to letting you adjust the tempo, o1.play lets you
choose among a variety of virtual instruments. You do that by inserting
the number of the instrument in square brackets within the parameter
string — right at the beginning, perhaps. (The number must be an
integer between 1 and 128.)
Let’s take out our recorder flutes — instrument number 75.
import o1._import o1._
In this context, the square brackets don’t have anything to do with
Scala programming more generally. They are just characters within a
string (inside the quotation marks). O1’s play command interprets
them as an instrument tag. (In the next chapter, 1.5, we will
find another use for square brackets in Scala programs.)
Inspect the following piece of code carefully. Consider what happens
as the commands are issued, one at a time. Track the value of each
var instrument = 13
val melody = "<<<h.>c#.d.e.f#.d.f#-.e#.c#.e#-.e.c.e-.<h.>c#.d.e.f#.d.f#.h.a.f#.d.f#.a-- "
var trollDance = "["+ instrument + "]" + melody + "/138"
instrument = 72
Which of the following describes what happens when the last line
of code is executed? Explore the phenomenon in the REPL as needed.
In addition to, or instead of, playing the strings, you can
try printing them out.
Suppose our goal is to add one more line to the six so that the program,
when run line by line, first plays the troll dance on instrument 13 (the
marimba) and then on instrument 72 (the clarinet).
Here’s the required line of code:
trollDance = "["+ instrument + "]" + melody + "/138"
We need to insert that line among the other six. What would its line number
be in the working program? Please enter a single integer between 1 and 7.
o1.play and MIDI sound synthesis
The play command supports instruments that are defined in the
General MIDI standard, where MIDI is short for Musical Instrument
Digital Interface. MIDI synthesizes sound on a variety of virtual
instruments; the quality of the output varies greatly. O1’s play
command is an easy-to-use, string-based interface to some of the
basic MIDI features.
You can find a numbered list of instruments on the midi.org web
In O1, we use MIDI sound for fun: for learning, not for serious
audio quality. We use strings to represent notes, not sound as such.
The digital representation of sound and recorded audio are topics for
Programming Studio 1.
o1.play and dots
The melody that we just played had a string representation with period-dots
here and there. The play command interprets each note followed by a dot
as a crisp-sounding staccato, in which the note has a shorter duration
and is followed by a short pause.
The data type of a variable determines which values you can store in the variable. A
variable’s type never changes, not even if the variable is a var. For instance, if you
have a variable of type String, you can assign only strings to it, as demonstrated below.
var title = "Ms."title: String = Ms.
title = "M.Sc."title: String = "M.Sc."
title = 12345Int(12345) <: String?
<console>:8: error: type mismatch;
found : Int(12345)
title = 12345
Interpreting error messages is a skill that you’ll develop as you gain experience. The
above message means something like:
“Is the integer 12345 some kind of string? Nope. Error: Data types
are incompatible; on the line title = 12345, the integer 12345
where a string should be.”
title = 12345
Sometimes it seems as if we can break the rule of type compatibility. One such scenario
arises when we assign an Int value to a variable of type Double, as at the end of this
var someNumber = 123.45someNumber: Double = 123.45
val evenFigure = 100evenFigure: Int = 100
evenFigure * evenFigureres8: Int = 10000
someNumber = evenFiguresomeNumber: Double = 100.0
someNumber * evenFigureres9: Double = 10000.0
The last assignment command, too, was valid: the Int value that we accessed through
evenFigure “serves as a Double”. But as you can tell from the last few lines of the
example, it’s not the Int that gets stored in someNumber but the corresponding Double
value. Using that Double in arithmetic yields more Doubles.
This interplay between Ints and Doubles is convenient when we need a program
component that should work on Doubles but that should also work similarly on
integers. Which is quite common.
Once upon a time, there were two var variables named hansel and gretel, who
had the same data type. The following code was then executed:
hansel = gretel
gretel = hansel
Which of the following claims best describes what happens to the values of the two
variables? Assume that the variables have been created and initialized to some values
and the two lines of code are then executed one at a time. Program in the REPL as
needed to explore the phenomenon.
In the code below, a couple of expressions have been replaced with question marks,
producing a little puzzle. Read the code and reflect on what it does to the values
of the two variables defined on the first two lines.
var first = ???
var second = ???
val helperVariable = first
first = second
second = helperVariable
println(first + ", " + second)
Now suppose that we know that the last line outputs "Tegan, Sara". What must have
been the initial value of the variable second?
You’ll be familiar already with the way the REPL replies with a res prefix when you
feed it an expression. In fact, what the REPL does here is create new val variables
whose names begin with res. You can use these variables just as you use variables that
you defined explicitly yourself:
1 + 1res10: Int = 2
res10 * 10res11: Int = 20
val total = res10 + res11total: Int = 22
You can make use of this fact as you experiment in the REPL. In this ebook, we don’t use
these res-prefixed variables, however. One of the reasons is that we wish to focus on
teaching you programming techniques that work outside of the REPL, too. The numbered res
variables are peculiar to the REPL environment.
Finally, here’s the concept map from the previous chapter, expanded with a few key
concepts from this one.
Please note that this section must be completed individually.
Even if you worked on this chapter with a pair, each of you should submit the form separately.
Time spent: (*) Required
Please estimate the total number of minutes you spent on this chapter (reading, assignments,
etc.). You don’t have to be exact, but if you can produce an estimate to within 15 minutes or
half an hour, that would be great.
Written comment or question:
You aren’t required to give written feedback. Nevertheless, please
do ask something, give feedback, or reflect on your learning!
(However, the right place to ask urgent questions about programs
that you’re currently working on isn’t this form but Piazza or the
lab sessions. We can’t guarantee that anyone will even see anything
you type here before the weekly deadline.)
Thousands of students have given feedback that has contributed to this ebook’s design.
Weeks 1 to 13 of the ebook, including the assignments and weekly bulletins, have been
written in Finnish and translated into English by Juha Sorva.
Weeks 14 to 20 are by Otto Seppälä. That part of the ebook isn’t available during the
fall term, but we’ll publish it when it’s time.
The appendices (glossary, Scala reference,
FAQ, etc.) are by Juha Sorva unless otherwise specified on the page.
The automatic assessment of the assignments has been programmed by Riku Autio, Jaakko
Kantojärvi, Teemu Lehtinen, Timi Seppälä, Teemu Sirkiä, and Aleksi Vartiainen.
The illustrations at the top of each chapter, and the similar drawings elsewhere in the
ebook, are the work of Christina Lassheikki.
The animations that detail the execution Scala programs have been designed by Juha Sorva and
Teemu Sirkiä. Teemu Sirkiä and Riku Autio have done the technical implementation, relying on
Teemu’s Jsvee and Kelmu
The other diagrams and interactive presentations in the ebook are by Juha Sorva.
The O1Library software
has been developed by Aleksi Lukkarinen and Juha Sorva. Several of its key components
are built upon Aleksi’s SMCL
The pedagogy of using tools from O1Library (such as Pic) for simple graphical programming
is inspired by the textbooks How to Design Programs by Flatt, Felleisen, Findler, and
Krishnamurthi and Picturing Programs by Stephen Bloch.
The course platform A+ has been created by
Aalto’s LeTech research group and is largely
developed by students. The current lead developer is Jaakko Kantojärvi; many other
students of computer science and information networks are also active on the project.
For O1’s current teaching staff, please see Chapter 1.1.
This chapter does injustice to music by Edvard Grieg. Thank you and sorry.