A problem posed by Paul Graham is that of creating a function that takes a single (numeric) argument and which returns another function that is an accumulator. The returned accumulator function in turn also takes a single numeric argument, and returns the sum of all the numeric values passed in so far to that accumulator (including the initial value passed when the accumulator was created).



Rules

The detailed rules are at http://paulgraham.com/accgensub.html and are reproduced here for simplicity (with additions in small italic text).

Before you submit an example, make sure the function
 Takes a number n and returns a function (lets call it g), that takes a number i, and returns n incremented by the accumulation of i from every call of function g(i).
Although these exact function and parameter names need not be used
 Works for any numeric type-- i.e. can take both ints and floats and returns functions that can take both ints and floats. (It is not enough simply to convert all input to floats. An accumulator that has only seen integers must return integers.) (i.e., if the language doesn't allow for numeric polymorphism, you have to use overloading or something like that)
 Generates functions that return the sum of every number ever passed to them, not just the most recent. (This requires a piece of state to hold the accumulated value, which in turn means that pure functional languages can't be used for this task.)
 Returns a real function, meaning something that you can use wherever you could use a function you had defined in the ordinary way in the text of your program. (Follow your language's conventions here.)
 Doesn't store the accumulated value or the returned functions in a way that could cause them to be inadvertently modified by other code. (No global variables or other such things.)
 E.g. if after the example, you added the following code (in a made-up language) where the factory function is called foo:
 x = foo(1); 
x(5); 
foo(3);
print x(2.3);
 It should print 8.3. (There is no need to print the form of the accumulator function returned by foo(3); it's not part of the task at all.)


Task

Create a function that implements the described rules.



It need not handle any special error cases not described above. The simplest way to implement the task as described is typically to use a closure, providing the language supports them.

Where it is not possible to hold exactly to the constraints above, describe the deviations.




 
; Accumulator factory
; Returns a function that returns the sum of all numbers ever passed in
; Build:
;   nasm -felf32 af.asm
;   ld -m elf32_i386 af.o -o af
 
global  _start
section .text
 
_start:
    mov eax, 0x2D       ; sys_brk(unsigned long brk)
    xor ebx, ebx        ; Returns current break on an error
    int 0x80            ; syscall
    push    eax         ; Save the initial program break
 
    push    2           ; Get an accumulator initialized to 2
    call    factory
    mov [acc1], eax     ; Save the pointer in acc1
 
    push    5           ; Get an accumulator initialized to 5
    call    factory
    mov [acc2], eax     ; Save the pointer in acc2
 
    push    4           ; Call acc1 with 4
    lea eax, [acc1]
    call    [eax]
 
    push    4           ; Call acc2 with 4
    lea eax, [acc2]
    call    [eax]
 
    push    -9          ; Call acc1 with -9
    lea eax, [acc1]
    call    [eax]
 
    push    13          ; Call acc1 with 13
    lea eax, [acc1]
    call    [eax]
 
    push    eax         ; Print the number, should be 10
    call    print_num
 
    push    -5          ; Call acc2 with -5
    lea eax, [acc2]
    call    [eax]
 
    push    eax         ; Print the number, should be 4
    call    print_num
 
    mov eax, 0x2D       ; Reset the program break
    pop ebx
    int 0x80
 
    mov eax, 0x01       ; sys_exit(int error)
    xor ebx, ebx        ; error = 0 (success)
    int 0x80
 
; int (*function)(int) factory (int n)
; Returns a pointer to a function that returns the sum of all numbers passed
; in to it, including the initial parameter n;
factory:
    push    ebp         ; Create stack frame
    mov ebp, esp
    push    ebx
    push    edi
    push    esi
 
    mov eax, 0x2D       ; Allocate memory for the accumulator
    xor ebx, ebx
    int 0x80
    push    eax         ; Save the current program break
    mov ebx, .acc_end   ; Calculate the new program break
    sub ebx, .acc
    push    ebx         ; Save the length
    add ebx, eax
    mov eax, 0x2D
    int 0x80
 
    pop ecx             ; Copy the accumulator code into memory
    pop eax             ; Set the returned address
    mov edi, eax
    mov esi, .acc
    rep movsb
    lea edi, [eax + 10] ; Copy the parameter to initialize accumulator
    lea esi, [ebp + 8]
    movsd
 
    pop esi             ; Tear down stack frame
    pop edi
    pop ebx
    mov esp, ebp
    pop ebp
    ret 4               ; Return and remove parameter from stack
 
.acc:                   ; Start of the returned accumulator
    push    ebp
    mov ebp, esp
    push    edi
    push    esi
 
    call    .acc_skip   ; Jumps over storage, pushing address to stack
    dd  0               ; The accumulator storage (32 bits)
.acc_skip:
    pop esi             ; Retrieve the accumulator using address on stack
    lodsd
    add eax, [ebp + 8]  ; Add the parameter
    lea edi, [esi - 4]
    stosd               ; Save the new value
 
    pop esi
    pop edi
    mov esp, ebp
    pop ebp
    ret 4
.acc_end:               ; End of accumulator
 
; void print_num (int n)
; Prints a positive integer and a newline
print_num:
    push    ebp
    mov ebp, esp
 
    mov eax, [ebp + 8]  ; Get the number
    lea ecx, [output + 10]  ; Put a newline at the end
    mov BYTE [ecx], 0x0A
    mov ebx, 10         ; Divisor
.loop:
    dec ecx             ; Move backwards in string
    xor edx, edx
    div ebx
    add edx, 0x30       ; Store ASCII digit
    mov [ecx], dl
    cmp eax, 0          ; Loop until all digits removed
    jnz .loop
 
    mov eax, 0x04       ; sys_write(int fd, char *buf, int len)
    mov ebx, 0x01       ; stdout
    lea edx, [output + 11]  ; Calulate length
    sub edx, ecx
    int 0x80
 
    mov esp, ebp
    pop ebp
    ret 4
 
section .bss
acc1:                   ; Variable that stores the first accumulator
    resd    1
acc2:                   ; Variable that stores the second accumulator
    resd    1
output:                 ; Holds the output buffer
    resb    11
 