ASM (x86 + I/O for Linux)
It does not matter how much your puny high level languages will struggle, it will still be just hidden instruction pointer manipulation. In the end it will be some sort of "goto" (jmp), unless you are bored enough to unroll loop in runtime.
You can test code on Ideone
You can also check out more refined version of this idea in Matteo Italia DOS codeMatteo Italia DOS code.
It starts with string of 0..9 and replaces it with A..J, no direct jumps used (so lets say that no "goto" happened), no recurrence either.
Code probably could be smaller with some abuse of address calculation, but working on online compiler is bothersome so I will leave it as it is.
Core part:
mov dl, 'A' ; I refuse to explain this line!
mov ebx, msg ; output array (string)
call rawr ; lets put address of "rawr" line on stack
rawr: pop eax ; and to variable with it! In same time we are breaking "ret"
add eax, 4 ; pop eax takes 4 bytes of memory, so for sake of stack lets skip it
mov [ebx], dl ; write letter
inc dl ; and proceed to next
inc ebx
cmp dl, 'J' ; if we are done, simulate return/break by leaving this dangerous area
jg print
push eax ; and now lets abuse "ret" by making "call" by hand
ret
Whole code
section .text
global _start
_start:
;<core>
mov dl, 'A'
mov ebx, msg
call rawr
rawr: pop eax
add eax, 4
mov [ebx], dl
inc dl
inc ebx
cmp dl, 'J'
jg print
push eax
ret
;</core>
; just some Console.Write()
print:
mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80
mov eax,1
xor ebx, ebx
int 0x80
section .data
msg db '0123456789',0xa
len equ $ - msg