if and switch
use fmt;
type color = enum {
RED,
ORANGE,
YELLOW,
GREEN,
BLUE,
VIOLET,
};
export fn main() void = {
let stock = [
(color::RED, 1),
(color::BLUE, 6),
(color::VIOLET, 1),
(color::ORANGE, 4),
];
fmt::println("Inventory:")!;
printstock(stock[0]);
printstock(stock[1]);
printstock(stock[2]);
printstock(stock[3]);
};
fn printstock(item: (color, int)) void = {
const color = item.0, amount = item.1;
fmt::printfln("{} paint\t{} liter{}",
colorstr(color), amount,
if (amount != 1) "s" else "")!;
};
fn colorstr(c: color) str = {
switch (c) {
case color::RED =>
return "Red";
case color::ORANGE =>
return "Orange";
case color::YELLOW =>
return "Yellow";
case color::GREEN =>
return "Green";
case color::BLUE =>
return "Blue";
case color::VIOLET =>
return "Violet";
};
};
Like many other programming languages hare supports if, else if, and else
for basic branching. They work as you would expect. An important note is that
if expressions, like most hare expressions, can appear in any expression that
can compute a value. The printstock function uses this to determine if "liter"
should be appended with an "s".
Switch expressions provide a more structured approach to branching. Based on a
single value, the switch value, one of several cases is selected. The switch
value can be any primitive type, such as ints, runes, str, and enum
values.
Note that switch expressions are required to be exhaustive, which means
that every possible value should have a corresponding branch. If you do not want
to handle every possibility individually, you can add a "default" branch by
omitting the value: case =>. This branch will be executed should no more
specific branch match. This is also possible with match cases that omit the
match type.
yield
use fmt;
use fs;
use io;
use os;
export fn main() void = {
const file = match (os::open(os::args[1])) {
case let f: io::file =>
yield f;
case let err: fs::error =>
fmt::fatalf("Unable to open {}: {}.",
os::args[1], fs::strerror(err));
};
match (io::copy(os::stdout, file)) {
case size =>
yield;
case let err: io::error =>
fmt::fatalf("copy: {}", fs::strerror(err));
};
};
Curly braces { } denote blocks of expressions which are evaluated one after
another. In many languages, these are decorative, but in hare they have a
semantic meaning: these introduce new compound expressions, and, like most other
expressions, these expressions can compute a result using the yield keyword.
for
for (binding; condition; afterthought)
The binding and afterthought may be omitted which works like while in other
languages:
for (true)
break can be used to terminate a loop early and continue can be used to skip
to the next iteration of the loop.