Awesome! Iâm so glad youâve chosen Verse for learning to program. Coding is (or can be, at least) one of the most fun hobbies/careers out there, so I hope I can impart some of that joy in these tutorials.
If you get stuck or have any questions as you work through the examples and exercises, please post @VerseCode on Facebook and Iâll do my best to help you out.
Supported Platforms
Before we get started, letâs make sure you have the right setup. Currently, Verse works on macOS 10.11 (El Capitan) or newer (it might work on Windows and Linux, but I havenât tested it).
Additionally, youâll need the latest version of one of these web browsers:
Support for more platforms (including mobile) is coming soon, but for now itâs just these. If thereâs a particular OS or browser you think I should support, just post on the Verse Facebook page. If enough people ask for it, Iâll figure out a way to make it work.
Hello, World!
Okay, youâve installed an awesome web browser and youâre ready to code! Right-click this link and open it in a new window to bring up Verse.
The white areaâthe left half of the screen, basicallyâis the editor, the place where weâll type our code. When the code runs, it will display things on the right half of the screen.
Weâll start with the classic introduction to coding: the âHello, Worldâ program, which just makes the text âHello, Worldâ (or whatever message we want) appear on the screen.
To start, click the big âSTARTâ button. Then type the code
below into the editor. To type the
{}
characters (programmers call them âcurly bracesâ),
hold shift
and use the keys just to the
right of P
(assuming you have an American keyboard). Note
that when you type an opening parenthesis (
or curly brace
}
, a matching )
or }
will be inserted automatically.
define({
})
This line of code forms the backbone of our program. All
our other code will go between the curly braces { ... }
.
Once youâve typed that out, the LOAD
button at the top of
the screen should be bright blue-green. This
indicates that the computer understood what you typed and
was able to load your code into its machinery
successfully. If the button is yellow instead, check your
work and make sure it matches the example. Computers are
very picky about the code theyâll accept.
Now letâs define a function that will put our âHello, Worldâ message on the screen. A function is a list of instructions for the computer that tell it how to perform some task and give us back the result. If you think of the computer as a restaurant cook, a function is like a recipe that tells it how to make one of the items on the menu.
To define a function, we first have to give it a name.
Most of the time when we create a function, we can choose
any name we want as long as it contains only letters and
numbers (no spaces or punctuation). However, weâre going
to give this function a very specific name: displayText
.
The name displayText
tells Verse to use this function to
determine what text will be shown on the screen when the
program runs.
After the name of the function, we need to put a pair
of parentheses ()
and a pair of curly braces {}
.
define({
displayText() {
}
})
When your code looks like the example above, you should
see the green LOAD
button again. Again, if itâs yellow,
check your work for mistakes.
If nothing you type seems to give you the green light at this point, just copy-paste the example code into the editor.
If youâve copy-pasted it and it still doesnât work, please message @VerseCode on Facebook and let me know.
Weâre almost done! We have a function, but it doesnât do
anything. We just need to add an instruction,
or statement, between the curly braces. The computer will
follow this instruction when it runs the displayText
function.
define({
displayText() {
return 'Hello, World!'
}
})
Here, weâre using the return
keyword to hand off the text
'Hello, World!'
to the computer. The text will then get
drawn on the screen. We surround the text in single quotes
so the computer knows where it begins and ends.
When youâre done typing, you should once again see the
green LOAD
light. And at this point, you should also see
the text Hello, World!
on the right side of the screen.
It works!
Experiments
Now that youâve got a working chunk of code, I encourage you to play around with changing it to see what works and what doesnât.
- Try changing the function name
displayText
to something else. What happens? - The quotes around âHello, World!â tell the computer exactly where the text starts and ends. Try changing âHello, World!â to âDoesnât workâ. What do you think is causing the problem?
- Change the text âHello, World!â to whatever message you want.
- Try deleting the spaces and indentation from the code. Which spaces are necessary and which ones arenât?
- Try adding more spaces between the words and punctuation. Are there places where adding spaces will break the code?
- What happens if you delete the
return
keyword?
Review
Congratulations! Youâve written your first program and taken your first steps into the world of Verse! Letâs review the key things weâve learned:
- In Verse, we write code on the left half of the screen, and see our programs run on the right half.
- Every program is wrapped in
define({ ... })
. - Programs are built by defining functions, which are like recipes the computer follows to make whatever we want.
- When we want to define a snippet of text that the computer should process, we surround it in single quotes so the computer knows exactly where it starts and ends.
- When a function with the name
displayText
return
s a piece of text, that text is shown on the screen when the program runs.
Shouting at the World
Our program is currently rather uninteresting. Letâs see if we can make it automatically transform our âHello, Worldâ greeting into ALL CAPS SO IT LOOKS LIKE ITâS SHOUTING.
define({
displayText() {
return uppercase('Hello, World!')
}
})
Here we see our first example of how to call, or use, a
function in JavaScript. Weâre calling a function named
uppercase
by mentioning its name
and following it with a
pair of parentheses. Between the parentheses, we feed in
some data: the text âHello, World!â. The function
processes the text and gives us back the result, which we
return
so it is displayed on the screen.
Returning to our functions-are-recipes metaphor: calling a function is like shouting to the cook âone order of fried applesauce for table 6, please!â. Except instead, weâre asking for âone order of uppercase hello world!â
Just to illustrate this, hereâs how weâd ask the computer for fried applesauce:
define({
displayText() {
return fried('applesauce')
}
})
And this would totally work if our computer knew how to
fry text. But thereâs no function named fried
, so this
program will give us an error if we try to run it.
You may be wondering where the uppercase
function comes
from. In other words, why does uppercase
work but fried
doesnât? The answer is pretty boring: the uppercase
function is just built into Verse. A list of built-in
functions and how to use them is available here will be
available once I get my act together.
The Beauty of Functions
If you just look at the output of our little program, itâs exactly the same as if weâd written
define({
displayText() {
return 'HELLO, WORLD!'
}
})
Thatâs because a function call like uppercase('Hello, World!')
stands in for the result of the function. You can replace
one with the other and the output of the program wonât
change. The five-dollar term for this is referential
transparency (and yes, you can totally impress people by
mentioning referential transparency at parties).
Of course, you may be wondering: why not just replace the
function call with the uppercased result? It would be a lot
simpler! But then we would be doing work that the computer
can do much more quickly and accurately. The nice thing
about calling uppercase
is that we can now convert any
text we want to all-caps, just by copy-pasting it into our
program. Try it with this paragraph! Just make sure you have
quotes around the text so the computer knows where it begins
and ends.
At this point, you may be starting to sense that functions
have a beautiful kind of usefulness. Once you know the name
of a function and what it does, itâs like having a new skill
that you can use everywhere. A good cook knows not only how
to make fried('applesauce')
, but fried('lamb chops')
or
fried('crème brÝlÊe')
too. Just as frying is a process that can
be applied to almost anything, uppercasing is a process
that can be applied to any text. In programming, this type
of simple process that can be applied to an infinity of
different objects is called an abstraction.
Talking Backwards
Letâs try out another function thatâs built into Verse:
reverse
, which takes a string of text and returns a
backwards version of it, so hello
becomes olleh
.
define({
displayText() {
return reverse('Hello, World!')
}
})
Experiments
- Try replacing âHello, World!â in the program above with a message of your choice.
- A word or phrase that is spelled the same forwards and
backwards is called a palindrome. Use the
reverse
function to demonstrate thattacocat
is a palindrome. Or try this epitaph for Napoleon:able was I ere I saw elba
. - Try writing a program that outputs the reversed, uppercase version of a string: that is, if you paste in the text âhello worldâ it should output âDLROW OLLEHâ. Hint: remember that a function call stands in for the result of the function.
- It seems like
reverse(uppercase('hello'))
anduppercase(reverse('hello'))
always produce the same output. Why do you think this is? - What do you expect
reverse(reverse('hello'))
to output? Try it!
Mirror Text
In this lesson, weâll deepen our knowledge of how to process and transform text. Weâll write a program that, given a word or phrase, creates a palindrome by âmirroringâ it, like this:
"hello" -> "helloolleh"
"rats live on " -> "rats live on no evil star"
We already know how to reverse text, so weâre halfway there! The tricky bit is, how do we output both the original text (the first half of the palindrome) and the reversed version (the second half)?
Letâs start simple by hardcoding the reversed text, rather
than using reverse
to generate it. We can glue the forward
and reversed text together using the +
operator.
define({
displayText() {
return 'hello' + 'olleh'
}
})
Run the program (if itâs not running already); at this
point, it should output helloolleh
.
Now, using the principle of referential transparency and our
knowledge of how reverse
works, we can replace 'olleh'
with reverse('hello')
:
define({
displayText() {
return 'hello' + reverse('hello')
}
})
When youâre done making that change, the output should still
be helloolleh
. Make sure youâre still seeing the green
LOAD
light too; if itâs yellow, the output youâre
seeing is likely from the previous version of the program,
with the hardcoded text.
Using Variables
Thereâs one more change we can make to improve this code.
The text 'hello'
is repeated twice, so if we want our
program to output a different palindrome, we have to change
it in two places, e.g.
define({
displayText() {
return 'rats live on ' + reverse('rats live on ')
}
})
Thatâs a lot of typing! Worse, having the text in two places makes it less clear that our program is designed to output a palindrome. If we changed just one of the places, the output would no longer be a palindrome:
define({
displayText() {
return 'rats live on ' + reverse('hello')
}
})
The way we can fix this is by using a variable. Variables are one of the most useful concepts in programming. A variable is like a container where you can store information (like text and numbers) that you arenât going to use right away but want to save for later.
Letâs add a variable called forwardsText
to our program to
store the text weâre going to reverse. The keyword let
tells the computer that weâre creating a new variable, and
the =
operator puts the value to its right into the
variable.
define({
displayText() {
let forwardsText = 'hello'
return 'hello' + reverse('hello')
}
})
You can read this in your head as âlet forwards text be
helloâ. Read it as dramatically as you like! It
has the authority of an autocratic proclamation. Rest
assured that now and henceforth, forwardsText
is
'hello'
.
We can use our newly minted variable in our return
statement, just by replacing the hardcoded value 'hello'
with the name of our variable. Like function calls, this
replacement follows the principle of referential
transparency: because weâre replacing the value 'hello'
with a variable thatâs storing the text 'hello'
, the
output of our program wonât change.
define({
displayText() {
let forwardsText = 'hello'
return forwardsText + reverse(forwardsText)
}
})
Now we can easily change our program to output any text we want!
define({
displayText() {
let forwardsText = 'rats live on '
return forwardsText + reverse(forwardsText)
}
})
Statements in Functions
So far, weâve only seen functions with one step, or
statementâand that statement has always started with
return
. Now that weâre using variables, weâve introduced
a second type of statementâthe let
statementâand now
we have to understand how the computer interprets functions
with multiple statements.
Fortunately, itâs not very complicated: statements within a
function run in top-down order. When running our program,
the computer starts with the let
statement, and only once the
variable has been created and the text stored does it
move on to the return
. Because of this strict ordering,
the let
statement must come before the return
statementâotherwise, the variable wonât exist when we try
to use it, and our program will crash.
Clean Code Tip: Naming Variables
In this tutorial we named our variable forwardsText
, but
we could have named it anything we wanted. (There are some
restrictions on variable names, though: they can only
contain uppercase and lowercase letters, numbers, and the
symbols $
and _
, and they canât start with a number.)
With this awesome power and freedom comes the responsibility
to choose good names for our variables.
In general, itâs good for variable names to be:
- descriptive: Imagine someone else is reading your code, trying to figure out what it does and why. Names that give clues about how the information in the variable is going to be used are going to be very helpful to that person! Even if youâre not planning on sharing your code with anyone, you might someday need to figure out what your code does after not looking at it for months. When choosing a name, ask yourself: âwill this jog my memory after Iâve forgotten what this code is supposed to do?â
- short: While descriptive names are great, very long
names are hard to type and make your code look cluttered.
We could have named our variable
textThatWeAreGoingToPassToReverseToCreateAPalindrome
but that would be far, far too long. Going to the other extreme, we could give our variables single-letter names. These can be mnemonic (e.g.t
fortext
), or simply sequential (if we have multiple variables, name thema
,b
,c
âŚ). Such short names sacrifice descriptiveness, but sometimes thatâs okay. - camelCased: Since spaces arenât allowed in variable names, itâs nice to have some other way to hint at where the word boundaries fall. Each word in a variable name (after the first) should start with a capital letter. This gives the name âhumpsâ, like a camelâhence the term âcamel caseâ.
Other names I considered for this variable include:
text
: Nice and short so itâs easy to type, but tells us very little about what this variable means to our program. Since we can see the value'hello'
is stored in the variable, we already know itâs text!halfPalindrome
: Very descriptive, but longer and harder to spell. It also presents a bit of a puzzle to someone whoâs not familiar with what the code is doingâthe concept of a âhalf palindromeâ is not something that most readers of our code will already have in mind. The mental effort it would take to solve this little puzzle could probably be better spent just reading and understanding the code.textToMirror
: This is the same length asforwardsText
, but focuses more on what weâre going to do to the text rather than what it is. A fine choice!forwards
: Since we already know the variable is storing text, why repeat that information in the name?toMirror
: See above.
You definitely donât have to think about every variable name this much, but itâs good to get in the habit of choosing names deliberately. When you start writing more complex code, good variable names will make the difference between manageable and incomprehensible.
Experiments
- Try changing the value stored in the
forwardsText
variable. Can you invent a new palindrome thatâs an actual phrase or sentence in English (or any language of your choice)? - Change the variable name following
let
tobroken
(donât change the places where the variable is used). What error do you see? - Change the variable name to whatever you want. Update the places where itâs used, too, so the program works.
-
What happens if you move the
return
statement up one line, so it comes before thelet
? For example:define({ displayText() { return forwardsText + reverse(forwardsText) let forwardsText = 'hello' } })
- Try to change the program so it outputs an âinside-outâ
palindromeâthat is, if the text stored in the variable
is
'hello'
, it should outputollehhello
.
Making an Interactive Program
The programs weâve written so far have an unfortunate shortcoming: in order to make them process different text, we have to change their code. That makes them next to useless for people who donât know how to program.
We need to make our programs interactive so anyone can use them. For example, it would be great if our âreverseâ program could prompt the user to type in the text they want to reverse, and then show them the reversed output.
In Verse, we create interactive programs by defining a
special function called run
. Weâll learn more about how
this function works in later tutorials; for now just
copy-paste the code below.
define({
process(input) {
return reverse(input)
},
*run() {
let input = yield waitForInput()
yield log(process(input))
yield retry(run)
}
})
Now when you click the âRunâ button, youâll see an input prompt at the bottom of the screen. It looks sort of like this:
> _
Type your name, or any message you like, and then hit the
return
key. You can type as many messages as you want,
hitting return
after each one, and the program will echo
back the reversed versions.