Davetown

/\___/\ /.:(0)(0)\ <<< ,____o> / / ,, \

Hare Cheat Sheet

March 28, 2025

#harelang

So I wrote a Hare cheat sheet. Why? For starters, I’ve long known that I’m the kind of person that learns well through examples. And why now? Well, it’s been over a year since I last wrote any Hare, and my grasp of the syntax has dulled after such a hiatus. It seemed like a good deal to create a reference for myself that would also give me a refresher in the process.

The code is shown at the end of this post and is also present as fizzbuzz.ha in this git repository. As the file name suggests, it’s a convoluted fizz buzz solution that takes a meandering walk through a number of Hare’s language features found in the intro tutorial.

Features touched on:

use fmt;
use math;
use os;
use strconv;
use strings;

const DEFAULT_MAX = 100u;
const RANGE: [2]uint = [1, 1024];

type fbzsymbol = enum {
	NONE,
	FIZZ,
	BUZZ,
	FIZZBUZZ,
};

type params = struct {
	numbers: []uint,
	debug: bool,
};

export fn main() void = {
	let max: uint = DEFAULT_MAX;
	if (len(os::args) >= 2) {
		max = match (strconv::stou(os::args[1])) {
		case let i: uint =>
			yield if (i >= RANGE[0] && i <= RANGE[1]) {
				yield i;
			} else {
				fmt::fatalf("value is out valid of range [{}, {}]\n", RANGE[0], RANGE[1]);
			};
		case let err: (strconv::invalid | strconv::overflow) =>
			fmt::fatalf("not a uint: {}\n", os::args[1]);
		};
	};

	let numbers: []uint = [];
	for (let i = 0z; i <= max; i += 1) {
		append(numbers, i: uint);
	};
	delete(numbers[0..2]);
	insert(numbers[0], 1);
	defer free(numbers);

	const fizzes = fizzbuzz(params { numbers = numbers, debug = true });
	free(fizzes);
};

fn fizzbuzz(p: params) []fbzsymbol = {
	let fizzes: []fbzsymbol = alloc([fbzsymbol::NONE...], len(p.numbers));
	let i = 0;
	for (let n .. p.numbers) {
		if (n % 3 == 0 && n % 5 == 0) {
			fizzes[i] = fbzsymbol::FIZZBUZZ;
		} else if (n % 3 == 0) {
			fizzes[i] = fbzsymbol::FIZZ;
		} else if (n % 5 == 0) {
			fizzes[i] = fbzsymbol::BUZZ;
		};
		if (p.debug) {
			fmt::println(fbzstr(n, fizzes[i]))!;
		};
		i += 1;
	};
	return fizzes;
};

fn fbzstr(n: uint, fbz: fbzsymbol) str = {
	switch (fbz) {
	case fbzsymbol::NONE =>
		return strconv::utos(n);
	case fbzsymbol::FIZZ =>
		return "FIZZ";
	case fbzsymbol::BUZZ =>
		return "BUZZ";
	case fbzsymbol::FIZZBUZZ =>
		return "FIZZBUZZ";
	};
};