Slide 15 of 74

assert and panic

In ordinary code, a failed assert stops the program
func total(prices: Int[]): Int {
	mut sum := 0
	for each p in prices {
		sum += p
	}
	return sum
}

proc main(): void {
	assert total([3, 4]) == 7    // holds: nothing happens
	echo "the basket adds up"
	assert total([3, 4]) == 8    // does not: the program stops, here
	echo "never reached"
}
What it prints
$ hive run basket.hive
the basket adds up
panic: hive: assertion failed: total([3, 4]) == 8
	  left:  7
	  right: 8

goroutine 1 [running]:
…
panic closes off a tail the checker cannot see is unreachable
func sign(n: Int): Int {
	if n > 0 {
		return 1
	} else if n < 0 {
		return -1
	} else if n == 0 {
		return 0
	}
	// Every Int is one of the three, but nothing proves it to the compiler.
	panic "an Int that is not positive, negative or zero: {n}"
}

proc main(): void {
	echo sign(-8)
}

assert cond says: this must hold. What happens when it does not is decided by where it is written. In ordinary code a failed assertion has proved the program wrong, so the program stops, printing the condition as it was written and, for == or !=, what each side came out as. Inside a test it has proved the test wrong, so the failure is recorded and the rest of the suite still runs — the testing slide shows that report. Either way its operands are evaluated exactly once, whether it holds or not.

panic value stops the program at once, printing value the way echo would — so an atom prints its name — and it takes any value rather than only a Bool. It never returns, so a path ending in panic counts as ended, which is what closes off a tail the checker cannot see is unreachable. An assert does not: one that holds carries on. A panic inside a test fails only that test, and one inside a service kills only that service.