Let's write a real program before any more theory. This chapter builds the classic first project: the computer picks a number between 1 and 100, you guess, and it tells you too low or too high until you find it.
Small as it is, this game touches most of what makes Crow itself: reading input, converting types, meeting your first error value, comparing with word operators, and looping. Everything it introduces gets a full chapter later — here we just use it all.
crow new guessing_game
cd guessing_game
Open main.co and replace its contents as we go. Run at any point with
crow run (compiled) or crow run -i (instant, interpreted).
First, ask for input:
1 2
raw = input['your guess: ']
log['you guessed: `raw`']input[prompt] prints the prompt, reads a line from the keyboard, and
returns it as a string. The backticks in 'you guessed: `raw`' are
Crow's string interpolation — any expression between paired backticks is
evaluated into the string.
The player typed a string; we need a number. int[...] converts:
1 2 3 4 5 6 7
n = int['42']
log[n]
log[n + 8]
bad = int['abc']
log[bad.ok]
log[bad.reason]expected output — from the book, verified by crow test --book
42
50
false
cannot convert 'abc' to intLook closely at the second half — this is your first encounter with Crow's
error model, and there is no try, no catch, no exception. int['abc']
simply returns a value that knows it failed. Every value in Crow
carries .ok and .reason; for successful values .ok is true and you
never think about it (notice n + 8 just works — values auto-unwrap).
For a failure, .ok is false and .reason says why.
What if you ignore the failure and use bad anyway? Crow refuses to guess:
an error value has no truth value, so a comparison or branch on it stops
the program (or returns the error from a function) rather than silently
picking a wrong path. Chapter 7 is entirely about this; for the game, all
we need is .ok.
1
secret = rand[1, 100]rand[min, max] returns a random integer in the range, inclusive.
Crow's comparison operators are words — eq, ne, lt, gt, lte,
gte — no shift key, no ==-vs-= bugs:
1 2 3 4 5 6 7 8 9
secret = 62
guess = 50
if guess eq secret
log['you got it!']
else if guess lt secret
log['too low']
else
log['too high']expected output — from the book, verified by crow test --book
too low(There is no elif keyword — else if is just an if in the else branch,
and it reads the same way.)
while true with break and continue gives the game loop. Here is the
complete program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
secret = rand[1, 100]
log['I am thinking of a number between 1 and 100.']
while true
raw = input['your guess: ']
n = int[raw]
if not n.ok
log['`raw` is not a number — try again']
continue
if n eq secret
log['you got it — `secret`!']
break
if n lt secret
log['too low']
else
log['too high']A session looks like this:
I am thinking of a number between 1 and 100.
your guess: fifty
fifty is not a number — try again
your guess: 50
too low
your guess: 75
too high
your guess: 62
you got it — 62!
Walk the error path once more, because it's the most Crow-shaped part:
when the player types fifty, int[raw] returns a failed value. We check
.ok, explain, and continue. If we hadn't checked, the very next line
— if n eq secret — would have refused to run on an error value and
stopped the program with the reason. Wrong input can never masquerade as
a wrong guess.
You've used: input and interpolation, int conversion, error values and
.ok, rand, word comparisons, if/else, and while/break/
continue. Chapter 3 now walks the everyday material properly, and
chapter 7 returns to error values in depth.