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 case
s is selected. The switch
value can be any primitive type, such as int
s, 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.