Subroutine calls in the ancient world, before computers had stacks or heaps
Early computers and some modern embedded systems lacked hardware stacks and heaps, forcing compilers and programmers to simulate function calls with global variables, fixed buffers, and self-modifying code. Commenters contrast this constrained world—where memory limits and non-recursive subroutines shaped software design—with today’s “YOLO” RAM usage, dynamic allocation, and higher-level abstractions. The thread branches into debates over artificial limits vs. flexible scaling, the safety and practicality of recursion, and how low-level constraints still influence design in areas like real-time systems, databases, and text editors.
Memory management and limitations
- Several comments contrast “pre-heap” programming (static sizing, explicit limits) with today’s more relaxed “YOLO RAM” attitude, especially in cloud services where failures are detected at scale and fixed by optimization or adding nodes.
- Others defend explicit limits as valuable constraints: they make behavior testable and predictable and help choose the right tool (e.g., DB vs cache vs queue).
- Debate over “artificial” limits: some see 32‑bit/4 GB limits as pure cost; others note that constraints enable system-level tricks (security, validation, optimization).
Stacks, heaps, and pre-stack techniques
- Many historical anecdotes: machines without hardware stacks, with shallow fixed-depth stacks, or with calls that stored return addresses in code or specific memory slots.
- Common workaround: secret global variables for parameters, locals, and return addresses; manual stacks in arrays; splitting memory so one structure grows from low addresses and another from high.
- Similar patterns show up in databases (slotted pages / forward-backward arrays), classic Mac OS heap/stack layout, and early word processors and text editors.
Recursion, reentrancy, and safety
- Strong disagreement on recursion in production:
- Critics call it a code smell in non‑FP languages, citing risk of stack overflow, non-obvious depth bounds, and issues with untrusted input (e.g., deeply nested JSON).
- Defenders argue recursion is natural and safe for many real problems (tree/AST traversals, balanced trees with logarithmic depth), widely deployed, and simpler than hand-managed stacks.
- Several note that recursion also breaks reentrancy when paired with static locals; systems without real stacks often cannot support recursion or reentrancy at all.
- Tail recursion and languages that optimize it are mentioned as mitigating factors, but not universally available.
Embedded and constrained systems
- Embedded/real‑time development still often avoids dynamic allocation; everything is statically sized to guarantee timing and avoid fragmentation.
- Stories from microcontrollers and smartcards: no real heap or GC, limited RAM/EEPROM, “Java-like” environments without free, and catastrophic failure modes from memory exhaustion or wear‑out.
Language, tools, and nostalgia
- References to classic sources (e.g., Knuth) and old machines (6502, PDP‑8, IBM 360, TI‑99/4A, Z80, early Macs) illustrate how hardware constraints shaped calling conventions and memory models.
- Some discuss text editing structures (gap buffers vs ropes) as modern echoes of pre-heap thinking.
- The title’s ambiguity (“ancient world before computers had stacks or heaps”) leads to playful discussion about garden‑path sentences and expectations of truly ancient (pre-computer) “stacks.”