kota's memex

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.