← Code Compare

Control Flow: loops & conditionals

The bread and butter of every imperative language: a for loop and an if. The task is identical in all seven - sum the integers 1..5, but use an if to skip the even numbers, then print the total of the odds (1 + 3 + 5 = 9). Because the accumulator is a single integer living in a register or on the stack, this topic touches no heap at all - no malloc, nothing to free - so it's a clean look at each language's loop and branch syntax before the memory-heavy topics. Note how the C-family share for (init; cond; step) while Zig, Hare, Odin, and Forth each spell iteration their own way.

Show: CC++HolyCZigHareOdinForth
C
#include <stdio.h>

int main(void) {
    int total = 0;                 /* accumulator: just a stack int */

    for (int i = 1; i <= 5; i++) {
        if (i % 2 == 0)
            continue;             /* skip even numbers */
        total += i;               /* add 1, 3, 5 */
    }

    printf("%d\n", total);        /* 9 */
    return 0;
}

Classic C for (init; cond; step) with if/continue to skip the evens. total is an automatic (stack) variable, so there is no heap and nothing to free - control flow here costs zero allocations.

C++
#include <iostream>

int main() {
    int total = 0;

    // Range-based for over a brace-init list: clean and idiomatic.
    for (int i : {1, 2, 3, 4, 5}) {
        if (i % 2 == 0)
            continue;            // skip even numbers
        total += i;              // 1 + 3 + 5
    }

    std::cout << total << '\n';  // 9
}

Modern C++ favors the range-based for (for (int i : {...})) over an index loop; if/continue filters the evens. The accumulator stays on the stack - no new/delete, no smart pointer needed - so RAII has nothing to clean up.

HolyC
// Top-level code runs in TempleOS - no main() needed.
I64 total = 0;
I64 i;

for (i = 1; i <= 5; i++) {
  if (i & 1)            // odd: low bit set
    total += i;         // add 1, 3, 5
}

Print("%d\n", total);   // 9

HolyC's for and if are C-like (here i & 1 tests oddness via the low bit). Top-level code runs with no main, and total is a plain I64 on the task stack - the per-task heap is never touched, so there's no MAlloc/Free.

Zig
const std = @import("std");

pub fn main() void {
    var total: i32 = 0;

    // No C-style for here: use a while with a continue-expression.
    var i: i32 = 1;
    while (i <= 5) : (i += 1) {
        if (@rem(i, 2) == 0) continue; // skip even numbers
        total += i;                    // 1 + 3 + 5
    }

    std.debug.print("{d}\n", .{total}); // 9
}

Zig has no C-style for; the idiom is while (cond) : (step), with the continue-expression after the :. if/continue skips the evens, and total is a stack var - Zig never hides allocations, so no allocator is involved here.

Hare
use fmt;

export fn main() void = {
	let total = 0;

	// Hare's for loop: for (init; cond; step) { ... }.
	for (let i = 1; i <= 5; i += 1) {
		if (i % 2 == 0)
			continue;       // skip even numbers
		total += i;             // 1 + 3 + 5
	};

	fmt::println(total)!;          // 9
};

Hare keeps a C-style for (init; cond; step) plus if/continue. The accumulator is a stack let with no alloc/free in sight; the trailing ! on fmt::println propagates any I/O error rather than ignoring it.

Odin
package main

import "core:fmt"

main :: proc() {
	total := 0

	// Odin's for has no parens; this is the C-style three-part form.
	for i := 1; i <= 5; i += 1 {
		if i % 2 == 0 {
			continue        // skip even numbers
		}
		total += i              // 1 + 3 + 5
	}

	fmt.println(total)             // 9
}

Odin spells every loop with the keyword for (no parentheses) - here the C-style init; cond; step form, with if/continue. total lives on the stack, so the implicit context.allocator is untouched: no new/delete.

Forth
\ DO ... LOOP runs the index from a START up to (LIMIT-1).
\ 6 1 DO ... LOOP gives I = 1,2,3,4,5. We keep the running
\ total on the data stack instead of in a variable.
: ODD-SUM ( -- n )
  0                       ( total=0 on the stack )
  6 1 DO                  ( loop I = 1..5 )
    I 2 MOD IF            ( odd? low result nonzero )
      I +                 ( add I to the running total )
    THEN
  LOOP ;                  ( -- total )

ODD-SUM .                 \ prints 9
CR

Forth's counted loop is LIMIT START DO ... LOOP, where I pushes the current index; IF ... THEN is the conditional (RPN: the flag is already on the stack). There are no named locals here - the running total is carried on the data stack, so nothing is allocated or freed.