What code actually is
You changed a few words in a text file and an app on your phone changed. This lesson explains the whole mechanism behind that — what code is, what the compiler does with it, and why the machine is so unforgivingly literal.
You typed text. An app changed.
Stop and notice how strange Lesson 0.3 was.
You opened a file, typed some letters between two quote marks, and a few minutes later a phone was showing those letters. No wires, no magic. Something in between turned your typing into behaviour.
That something is worth understanding properly, because from here on you will be writing lines far less obvious than Text("Hello, Amara"), and the difference between a good beginner and a frustrated one is almost entirely whether they know what the machine is doing with their text.
Imagine a friend who will do absolutely anything you ask, perfectly, at enormous speed — and who thinks about nothing at all.
You say "make me a sandwich". They stand there. They do not know what a sandwich is.
So you write it out: take two slices of bread. Put butter on one side of each. Put cheese between them. Cut it in half.
They do it, flawlessly, in a fraction of a second. Then you notice you wrote "put butter on one side of each" and they buttered the outside. They did not think that seems wrong, because they never think anything. They did exactly what you wrote.
That is . Total obedience, zero judgement. Every frustrating hour you will ever spend debugging comes down to this: the machine did what you wrote, and what you wrote was not what you meant.
Code is text. That is not a simplification.
MainActivity.kt is a text file. If you emailed it to yourself and opened it in a notes app, you would see exactly the same characters. There is nothing hidden in it, no invisible layer, no special format.
What makes it code is that a particular program is willing to read it: the .
What the compiler does with your text
1MainActivity.kt the text you typed
2 |
3 | the Kotlin compiler reads it
4 v
5 .class files bytecode
6 |
7 | a tool called d8 repacks it
8 v
9 classes.dex what Android actually runsThe reads your file the way a very strict teacher reads an essay. First it checks the grammar — the . Is every bracket closed? Does every quote have a partner? Is Text a thing that exists?
If anything is wrong it stops and tells you, and no app is produced. If everything is right, it translates your Kotlin into — compact numbered instructions that no human would want to read. Then d8 repacks that into , and Android runs it.
Two things follow from this, and both are good news.
Your mistakes are caught before anyone sees them. Most errors happen at build time, on your phone, with a file name and a line number attached. That is enormously kinder than an app failing in a stranger's hands.
Your formatting is thrown away. Spacing, blank lines, indentation, — none of it survives compilation. It is all there for humans. Which means you can lay code out purely for readability, at zero cost.
Everything code does is one of three things
Any line of code you ever meet is doing one of these.
| It is doing | Looks like | Meaning |
|---|---|---|
| Naming something | val name = "Amara" | Put this value somewhere and call it name. |
| Doing something | Text("Hi") | Carry out this instruction now. |
| Deciding something | if (lives > 0) { ... } | Only do the next bit under this condition. |
That is the entire vocabulary. Part 1 spends nineteen lessons making you fluent in it, but there is no fourth category waiting to ambush you.
Reading a real piece of code
Here is a version of your Greeting that does all three-ish things at once. It runs — you will put it in your app at the end of this lesson.
lives here is an ordinary local value, not . It is worked out fresh each time Greeting runs and nothing changes it afterwards. Values that change while the user watches need remember, and Part 3 covers that properly.
Words Kotlin owns, and words you own
Some words in that code belong to Kotlin and mean one fixed thing. They are :
fun, val, var, if, else, class, return, package, import. There are about seventy of them in the whole language, and you will pick them up without ever sitting down to memorise a list.
Everything else — Greeting, name, lives — is a name you chose. You could rename all three and the app would behave identically:
1@Composable
2fun q() {
3 val x = "Amara"
4 var y = 3
5 y = y - 1
6 Text("$x has $y lives left")
7}The compiler cannot tell the difference. Your future self absolutely can. Names are the cheapest documentation there is, so spend them.
Why the machine is so literal
Three rules that account for most first-week errors.
Capitals matter. Text and text are two different names, as different as dog and cat. Kotlin's convention is that types and composables start with a capital, and your values and functions start lower case.
Spelling matters, and there is no "did you mean". pritnln is not a near-miss, it is an unknown word. The compiler will say Unresolved reference and stop. Use and let the editor spell things for you.
Symbols come in pairs. Every ( needs a ). Every { needs a }. Every " needs a closing ". Pocket Studio adds the closing one automatically when you type the opening one — let it, and do not delete its work.
Whitespace, on the other hand, does not matter to Kotlin. You could put the whole Greeting function on one line and it would compile. It would also be unreadable on a 60-character screen, which is the only reason anyone cares.
Put the walkthrough code into your own app and watch it run.
- Open Hello Pocket → MainActivity.kt.
- Scroll to the bottom, to
fun Greeting(). - Retype its body to match the seven-line walkthrough above —
val name,var lives, the subtraction, then theText(...)line. Put your own name in the quotes instead ofAmara. - Type it rather than copying it. Watch for red underlines as you go; if one appears, sort out that line before moving on.
- Tap Build → Run ▶. Under a minute.
- The screen should read Amara has 2 lives left. Not 3 — line 5 subtracted one before the text was built.
- Now break it deliberately: change
var lives = 3toval lives = 3and press Run. Read the error that appears. Then change it back. - Break it a second way: change
Texttotext. Read that error too, then fix it. You have now seen the two most common errors in Kotlin, on purpose, with nothing at stake.
name and nam are unrelated words as far as the compiler is concerned.Text. Lower-case text is a different name, and nothing defines it.Text("..."). As a rule, anything you did not name yourself — Text, Column, MaterialTheme — starts with a capital letter.val, which means "set once, never changed", and then tried to change it.var, or work out the final value in one go and keep the val. Prefer the second when you can — a value nothing can change is a value nothing can break.{ was opened and never closed. The compiler read all the way to the end of the file still waiting, which is why the reported line is often the last line rather than the real mistake.Text("$lives"). Part 1.2 covers types properly.- is plain text. What makes it special is that a is willing to read it.
- The compiler checks your , then translates your text into and finally . Your spacing and are discarded — they exist for humans.
- Every line does one of three things: names something, does something, or decides something.
- like
fun, and belong to Kotlin. Every other name is yours, so choose them for your future self. - Capitals matter, spelling matters, and brackets come in pairs. Those three account for most early errors.
- Next: those errors, properly. How to read a Kotlin error, a Gradle failure and a crash, and why the first error is the only one worth reading.