Accumulator factory

From Rosetta Code
Jump to: navigation, search
Task
Accumulator factory
You are encouraged to solve this task according to the task description, using any language you may know.

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).

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
  1. 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
  2. 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)
  3. 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.)
  4. 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.)
  5. 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.)

The purpose of this task is to 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.

Contents

[edit] ABAP

ABAP, unfortunately, has no first order functions, nor does its OO paradigm implement method overloading. One potential solution to this problem is to use classes to maintain the state, with the import/export parameters being defined as type 'any', so that the resultant type is calculated dynamically.

Another possible solution would be to use the languages in-built JavaScript processing capabilities to dynamically construct a JS source at run-time, which implements the JS Accumulator factory.

[edit] Object Oriented Solution

report z_accumulator
class acc definition.
public section.
methods:
call importing iv_i type any default 0 exporting ev_r type any,
constructor importing iv_d type f.
private section.
data a_sum type f.
endclass.
 
class acc implementation.
method call.
add iv_i to a_sum.
ev_r = a_sum.
endmethod.
 
start-of-selection.
 
data: cl_acc type ref to acc,
lv_ret2 type f,
lv_ret1 type i.
 
create object cl_acc exporting iv_d = 1.
cl_acc->call( exporting iv_i = 5 ).
cl_acc->call( exporting iv_i = '2.3' importing ev_r = lv_ret2 ).
cl_acc->call( exporting iv_i = 2 importing ev_r = lv_ret1 ).
write : / lv_ret2 decimals 2 exponent 0 left-justified, / lv_ret1 left-justified.
Output:
 8.30
10

[edit] JavaScript Solution

data: lv_source type string,
cl_processor type ref to cl_java_script,
lv_ret type string.
 
cl_processor = cl_java_script=>create( ).
concatenate
'function acc(sum) { '
' return function(n) { '
' return sum += n;'
' }; '
' }; '
' var x = acc(1); '
' x(5);'
' var ret = acc(3).toString();'
' ret = ret + x(2.3);'
into lv_source.
lv_ret = cl_processor->evaluate( lv_source ).
 
if cl_processor->last_condition_code <> cl_java_script=>cc_ok.
write cl_processor->last_error_message.
else.
write lv_ret.
write / 'Done'.
endif.
#function (n) {#    return sum += n;#}#8.3

[edit] ActionScript

Closures work the same in ActionScript as in JavaScript. ActionScript will transparently convert integers to reals if the function is given a real argument, but the typeof operator must be used to ensure the function isn't sent invalid arguments, such as strings (which would silently convert the accumulated number to a string without throwing an error).

Translation of: Javascript
//Throw an error if a non-number argument is used. (typeof evaluates to
// "number" for both integers and reals)
function checkType(obj:Object):void {
if(typeof obj != "number")
throw new ArgumentError("Expected integer or float argument. Recieved " + typeof obj);
}
function accumulator(sum:Object):Function {
checkType(sum);
return function(n:Object):Object {checkType(n); return sum += n};
}
var acc:Function=accumulator(2);
trace(acc(10));
trace(acc(4));
trace(acc("123")); //This causes an ArgumentError to be thrown.

[edit] Ada

with Accumulator;
with Ada.Text_IO; use Ada.Text_IO;
 
procedure Example is
package A is new Accumulator;
package B is new Accumulator;
begin
Put_Line (Integer'Image (A.The_Function (5)));
Put_Line (Integer'Image (B.The_Function (3)));
Put_Line (Float'Image (A.The_Function (2.3)));
end;
generic package Accumulator is
 
-- This Ada generic package represents an accumulator factory.
-- The required function is provided as The_Function.
-- The first call to The_Function sets the initial value.
-- (Marius Amado-Alves)
 
function The_Function (X : Integer) return Integer;
function The_Function (X : Integer) return Float;
function The_Function (X : Float) return Float;
end;
package body Accumulator is
 
-- The accumulator lives through three states. It is in Virgin_State
-- before any use of The_Function. It changes to Integer_State or
-- Float_State, according to the input type used. The accumulation is
-- memorized in variable I or F, according to the state. Float_State,
-- once reached, is never left. A Float output on an Integer_State is
-- simply a conversion, sans effect on state. (Marius Amado-Alves)
 
type State_T is (Virgin_State, Integer_State, Float_State);
State : State_T := Virgin_State;
I : Integer;
F : Float;
 
function The_Function (X : Float) return Float is
begin
case State is
when Virgin_State =>
State := Float_State;
F := X;
return F;
when Integer_State =>
State := Float_State;
F := Float (I) + X;
return F;
when Float_State =>
F := F + X;
return F;
end case;
end;
 
function The_Function (X : Integer) return Float is
begin
case State is
when Virgin_State =>
State := Integer_State;
I := X;
return Float (I);
when Integer_State =>
I := I + X;
return Float (I);
when Float_State =>
F := F + Float (X);
return F;
end case;
end;
 
function The_Function (X : Integer) return Integer is
begin
case State is
when Virgin_State =>
State := Integer_State;
I := X;
return I;
when Integer_State =>
I := I + X;
return I;
when Float_State =>
F := F + Float (X);
return Integer (F);
end case;
end;
 
end;

[edit] Aikido

Translation of: Javascript
function accumulator (sum:real) {
return function(n:real) { return sum += n }
}
 
var x = accumulator(1)
x(5)
println (accumulator)
println (x(2.3))
Output:
accumulator
8.3

[edit] ALGOL 68

Translation of: aikido
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

Note: Standard ALGOL 68's scoping rules forbids exporting a procedure (or format) out of it's scope (closure). Hence this specimen will run on ELLA ALGOL 68, but is non-standard. For a discussion of first-class functions in ALGOL 68 consult "The Making of Algol 68" - C.H.A. Koster (1993).

MODE NUMBER =  UNION(INT,REAL,COMPL);
 
PROC plus = (NUMBER in a, in b)NUMBER: (
CASE in a IN
(INT a): CASE in b IN (INT b): a+b, (REAL b): a+b, (COMPL b): a+b ESAC,
(REAL a): CASE in b IN (INT b): a+b, (REAL b): a+b, (COMPL b): a+b ESAC,
(COMPL a): CASE in b IN (INT b): a+b, (REAL b): a+b, (COMPL b): a+b ESAC
ESAC
);
 
main: (
 
# now override the + and +:= OPerators #
OP + = (NUMBER a, b)NUMBER: plus(a,b);
 
OP +:= = (REF NUMBER lhs, NUMBER rhs)NUMBER:
lhs := lhs + rhs;
 
PROC accumulator = (REF NUMBER sum)PROC(NUMBER)NUMBER:
(NUMBER n)NUMBER:
sum +:= n;
 
PROC (NUMBER)NUMBER x = accumulator(LOC NUMBER := 1);
x(5);
print(("x:",x(2.3), new line));
 
PROC (NUMBER)NUMBER y = accumulator(LOC NUMBER := 100);
y(500);
print(("y:",y(230), new line));
 
print(("x:",x(0), new line))
 
)
Output:
x: +.830000000000000e +1
y:        +830
x: +.830000000000000e +1

[edit] AppleScript

This has one deviation. AppleScript needs a script object for the closure on the sum n. So this factory returns a script object, not a handler by itself. One must call the handler through its script object, as in x's call(1).

on accumulator(n)
-- Returns a new script object
-- containing a handler.
script
on call(i)
set n to n + i -- Returns n.
end call
end script
end accumulator
 
set x to accumulator(10)
log x's call(1)
set y to accumulator(5)
log y's call(2)
log x's call(3.5)
-- Event Log: (*11*) (*7*) (*14.5*)

[edit] Argile

Works with: Argile version 1.1.1
use std, array
 
let A = accumulator 42
print(A 0)
print(A 1)
print(A 10)
print(A 100)
 
let B = accumulator 4.2
print(B 0)
print(B 1)
print(B 10.0)
print(B 100.4)
 
~A ; ~B
(: use dbg; check mem leak :)
 
(: accumulator call :)
=: <accumulator a> <num x> := -> (a.t)
call ((a.func) as function(any)(a.t)->(a.t)) with (a.data) ((Cgen x) as a.t)
 
(: accumulator constructors :)
.: accumulator <int x> :. -> int accumulator
(val (int accumulator) A).init(x)
(A as Accumulator).func = ( .:<int& accu, int x>:. ->int {accu += x; accu} )
A
 
.: accumulator <real x> :. -> real accumulator
(val (real accumulator) A).init(x)
(A as Accumulator).func = ( .:<real&accu,real x>:. ->real{accu += x; accu} )
A
 
=: <accumulator& a>.init <num x> :=
a = new (Accumulator)
a.data = (new array of 1 a.t)
*(a.data as (a.t*)) = Cgen x
 
(: accumulator destructor :)
.: del Accumulator <Accumulator a>:.
free a.data
free a
=: ~ <accumulator a> := {del Accumulator a}
 
(: accumulator type :)
class Accumulator
function func
any data
 
=: [<type t=(int)>] accumulator := -> type
Accumulator.prefix
Accumulator.suffix
 
autocast accumulator<->Accumulator

[edit] BBC BASIC

This code works by copying the function FNdummy() onto the heap and returning a pointer to it.

      x = FNaccumulator(1)
dummy = FN(x)(5)
dummy = FNaccumulator(3)
PRINT FN(x)(2.3)
END
 
DEF FNaccumulator(sum)
LOCAL I%, P%, Q%
DIM P% 53 : Q% = !^FNdummy()
FOR I% = 0 TO 49 : P%?I% = Q%?I% : NEXT
P%!I% = P% : sum = FN(P%+I%)(sum)
= P%+I%
 
DEF FNdummy(n)
PRIVATE sum
sum += n
= sum

[edit] Bracmat

Notice that Bracmat has no floating point numbers, only rational numbers.

( ( accumulator
=
.
' ( add sum object
. (object=add=$arg+!arg)
& !(object.add):?sum
& '($($sum)+!arg):(=?(object.add))
& !sum
)
)
& accumulator$1:(=?x)
& x$5
& accumulator$3
& out$(x$23/10)
)

Output:

83/10

[edit] Brat

accumulator = { sum |
{ n | sum = sum + n }
}
 
x = accumulator 1
x 5
accumulator 3 #Does not affect x
p x 2.3 #Prints 8.3 (1 + 5 + 2.3)

[edit] C

Deviation: Not in standard C, but several compilers include the typeof operator as an extension which can be used like a typedef. Functions must be defined outside of the main program body and they retain the same type throughout their life. C11 is supposed to give us some Type-generic macro expressions.

#include <stdio.h>
//~ Take a number n and return a function that takes a number i
#define ACCUMULATOR(name,n) __typeof__(n) name (__typeof__(n) i) { \
static __typeof__(n) _n=n; LOGIC; }

//~ have it return n incremented by the accumulation of i
#define LOGIC return _n+=i
ACCUMULATOR(x,1.0)
ACCUMULATOR(y,3)
ACCUMULATOR(z,'a')
#undef LOGIC
int main (void) {
printf ("%f\n", x(5)); /* 6.000000 */
printf ("%f\n", x(2.3)); /* 8.300000 */
printf ("%i\n", y(5.0)); /* 8 */
printf ("%i\n", y(3.3)); /* 11 */
printf ("%c\n", z(5)); /* f */
return 0;
}

[edit] C++

Deviation: The return type is wrong when the accumulator is called with an integer argument after is has been called with a float argument.

#include <iostream>
 
class Acc
{
public:
Acc(int init)
: _type(intType)
, _intVal(init)
{}
 
Acc(float init)
: _type(floatType)
, _floatVal(init)
{}
 
int operator()(int x)
{
if( _type == intType )
{
_intVal += x;
return _intVal;
}
else
{
_floatVal += x;
return static_cast<int>(_floatVal);
}
}
 
float operator()(float x)
{
if( _type == intType )
{
_floatVal = _intVal + x;
_type = floatType;
return _floatVal;
}
else
{
_floatVal += x;
return _floatVal;
}
}
private:
enum {floatType, intType} _type;
float _floatVal;
int _intVal;
};
 
int main()
{
Acc a(1);
a(5);
Acc(3);
std::cout << a(2.3f);
return 0;
}
Works with: C++11

The following is similar to the above, using lambda functions from C++11. Note that we declared the lambda mutable, which allows us to modify variables that were captured by value. This feature allows us to maintain mutable state, which is essential for an accumulator.

It suffers from the same deviation as the former, where the return type is wrong when the accumulator is called with a float argument after is has been called with an integer argument.

#include <iostream>
#include <functional>
 
template <typename T>
std::function<T(T)> makeAccumulator(T sum) {
return [=](T increment) mutable {
return sum += increment;
};
}
 
int main() {
auto acc = makeAccumulator<float>(1);
acc(5);
makeAccumulator(3);
std::cout << acc(2.3) << std::endl;
return 0;
}

[edit] C#

Works with: C sharp version 4.0
using System;
 
class Program
{
static Func<dynamic, dynamic> Foo(dynamic n)
{
return i => n += i;
}
 
static void Main(string[] args)
{
var x = Foo(1);
x(5);
Foo(3);
Console.WriteLine(x(2.3));
}
}

[edit] Clay

To my knowledge Clay does not admit of an elegant solution to this problem, although it should be stated that I am still exploring the language. But a clean solution mirroring that for other static languages is quite simple (one in which the operative numeric type is constrained by the original call to acc):

acc(n) {
return (m) => {
n = n + m;
return n;
};
}
 
main() {
var x = acc(1.0);
x(5);
acc(3);
println(x(2.3)); // Prints “8.300000000000001”.
}

Although statically typed, due to Clay’s everywhere-genericity this has the advantage of working out of the box for any type that defines addition:

    var y = acc(Vector[Char]("Hello"));
println(y(" World!")); // Prints "Hello World!”.

But you could constrain the function to numeric types were you so inclined:

[N | Numeric?(N)] acc(n: N) {
return (m) => {
n = n + m;
return n;
};
}

One could go crazy with tagged unions and runtime dispatching to rig something up that adhered more closely to the problem’s specification. But I know of no easier way to “change types” in the fashion necessary.

[edit] Clojure

The atom function creates an atomically updatable identity holding a value. The swap! function atomically updates the atom's value, returning the new value. The function returned from an accum call satisfies all the requirements.

(defn accum [n]
(let [acc (atom n)]
(fn [m] (swap! acc + m))))

Similarly, a ref could be used.

(defn accum [n]
(let [acc (ref n)]
#(dosync (alter acc + %))))

[edit] CoffeeScript

accumulator = (sum) ->
(n) -> sum += n
 
f = accumulator(1)
console.log f(5)
console.log f(2.3)

[edit] Common Lisp

Translation of: TXR
(defun accumulator (sum)
(lambda (n)
(incf sum n)))

Example usage:

(defvar x (accumulator 1))
(funcall x 5)
(accumulator 3)
(funcall x 2.3)
Output:
X
6
#<CLOSURE :LAMBDA (N) (SETF SUM (+ SUM N))>
8.3

[edit] D

import std.stdio;
 
void main() {
auto x = acc(1);
x(5);
acc(3);
writeln(x(2.3));
}
 
auto acc(U = real, T)(T initvalue) { // U is type of the accumulator
auto accum = cast(U)initvalue ;
return (U n) { return accum += n ; } ;
}

[edit] Dart

The => operator is Dart's special syntax for single line closures. When you use it the value of the expression is automatically returned without the return statement.

note: Function is the return type of the accumulator function, not the keyword used to define functions. There is no function keyword in Dart. The return type is optional, just like all types in Dart. The declaration could just be: accumulator(var n) => ...

Function accumulator(var n) => (var i) => n += i;
 
void main() {
var a = accumulator(42);
print("${a(0)}, ${a(1)}, ${a(10)}, ${a(100)}");
 
var b = accumulator(4.2);
print("${b(0)}, ${b(1)}, ${b(10.0)}, ${b(100.4)}");
}
Output:
42, 43, 53, 153
4.2, 5.2, 15.2, 115.60000000000001

[edit] Déjà Vu

accum n:
labda i:
set :n + n i
n
 
local :x accum 1
drop x 5
drop accum 3
!print x 2.3

[edit] E

def foo(var x) {
return fn y { x += y }
}

[edit] Elena

#define system.
#define system'dynamic.
 
#symbol Function =
(:x) [ self append:x ].
 
#symbol Accumulator = (:anInitialValue)
[ Extension(Function, Variable new:anInitialValue) ].
 
#symbol Program =
[
#var x := Accumulator:1.
 
x:5.
 
#var y := Accumulator:3.
 
console write:(x:2.3r).
].

[edit] Erlang

Erlang doesn't allow for mutable variables, but does have variable capture in closures. By spawning a process which loops endlessly, incrementing the sum and returning it to the caller, this mutable state can be imitated.

 
-module(acc_factory).
-export([loop/1,new/1]).
 
loop(N)->
receive
{P,I}->
S =N+I, P!S, loop(S)
end.
 
new(N)->
P=spawn(acc_factory,loop,[N]),
fun(I)->
P!{self(),I},
receive
V-> V
end
end.
 

[edit] Factor

:: accumulator ( n! -- quot ) [ n + dup n! ] ;
 
1 accumulator
[ 5 swap call drop ]
[ drop 3 accumulator drop ]
[ 2.3 swap call ] tri .

[edit] Fantom

The accumulator function is a little unwieldy using multiple ifs to maintain the type of 'sum' until forced to change. Again, a result of the three concrete Num types, Int, Float and Decimal, all being separated in the API.

class AccumulatorFactory
{
static |Num -> Num| accumulator (Num sum)
{
return |Num a -> Num|
{ // switch on type of sum
if (sum is Int)
{ // and then type of a
if (a is Int)
return sum = sum->plus(a)
else if (a is Float)
return sum = sum->plusFloat(a)
else
return sum = sum->plusDecimal(a)
}
else if (sum is Float)
{
if (a is Int)
return sum = sum->plusInt(a)
else if (a is Float)
return sum = sum->plus(a)
else
return sum = sum->plusDecimal(a)
}
else // if (sum is Decimal)
{
if (a is Int)
return sum = sum->plusInt(a)
else if (a is Float)
return sum = sum->plusFloat(a)
else
return sum = sum->plus(a)
}
}
}
 
public static Void main ()
{
x := accumulator (3.1)
y := accumulator (3f)
echo (x(5)) // the Decimal sum combines with an Int
echo (x(2))
echo (y(5.1)) // the Float sum combines with a Decimal
 
x = accumulator (1)
x (5)
accumulator (3)
echo (x(2.3)) // the Int sum is now a Decimal
}
}

[edit] Forth

Forth is untyped; this works on integers.

: accumulator
create ( n -- ) ,
does> ( n -- acc+n ) tuck +! @ ;
 
0 accumulator foo
 
1 foo . \ 1
2 foo . \ 3
3 foo . \ 6

[edit] F#

A statically typed version is not possible, but it is quite easy to write dynamically typed functions in F#:

// dynamically typed add
let add (x: obj) (y: obj) =
match x, y with
| (:? int as m), (:? int as n) -> box(m+n)
| (:? int as n), (:? float as x)
| (:? float as x), (:? int as n) -> box(x + float n)
| (:? float as x), (:? float as y) -> box(x + y)
| _ -> failwith "Run-time type error"
 
let acc init =
let state = ref (box init)
fun y ->
state := add !state (box y)
!state
 
do
let x : obj -> obj = acc 1
printfn "%A" (x 5) // prints "6"
acc 3 |> ignore
printfn "%A" (x 2.3) // prints "8.3"

Actually, it is possible to create a statically typed version by using an inline accumulator creation function.

let inline makeAccumulator init =
let acc = ref init
fun i ->
acc := !acc + i
!acc
 
do
let acc = makeAccumulator 1.0 // create a float accumulator
 
acc 5.0 |> ignore
let _ = makeAccumulator 3 // create an unused integer accumulator
printfn "%A" (acc 2.3)
Output:
8.3

[edit] GAP

accu := function(n)
local f, v;
v := n;
f := function(a)
v := v + a;
return v;
end;
return f;
end;
 
a := accu(0);
# function( a ) ... end
b := accu(100);
# function( a ) ... end
a(6);
# 6
b(6);
# 106
a(1);
# 7
b(1);
# 107
# These functions also accept other types, as long as addition is meaningful
b(1/FLOAT_INT(3))
# 107.333
a(2/3);
# 23/3
a([1, 2, 3]);
# [ 26/3, 29/3, 32/3 ]

[edit] Go

Small deviation on condition 2. The task specifies to handle all numeric types, and only int and float64 are shown here. The technique would extend to all types just as easily, but Go has lots of numeric types and the program would be big.

package main
 
import "fmt"
 
func accumulator(sum interface{}) func(interface{}) interface{} {
return func(nv interface{}) interface{} {
switch s := sum.(type) {
case int:
switch n := nv.(type) {
case int:
sum = s + n
case float64:
sum = float64(s) + n
}
case float64:
switch n := nv.(type) {
case int:
sum = s + float64(n)
case float64:
sum = s + n
}
default:
sum = nv
}
return sum
}
}
 
func main() {
x := accumulator(1)
x(5)
accumulator(3)
fmt.Println(x(2.3))
}
Output:
8.3

[edit] Groovy

Solution:

def accumulator = { Number n ->
def value = n;
{ it = 0 -> value += it}
}

Test:

def x = accumulator(1)
 
println x()
assert x() instanceof Integer
 
println x(5)
assert x() instanceof Integer
 
def y = accumulator(3)
println y()
assert y() instanceof Integer
 
println x(2.3)
assert x() instanceof BigDecimal
 
println y(10)
assert y() instanceof Integer
 
println y(200L)
assert y() instanceof Long
 
println y(2.25D)
assert y() instanceof Double
Output:
1
6
3
8.3
13
213
215.25

[edit] Haskell

Translation of: Ruby
import Control.Monad.ST
import Data.STRef
 
accumulator :: (Num a) => a -> ST s (a -> ST s a)
accumulator sum0 = do
sum <- newSTRef sum0
return $ \n -> do
modifySTRef sum (+ n)
readSTRef sum
 
main :: IO ()
main = print foo
where foo = runST $ do
x <- accumulator 1
x 5
accumulator 3
x 2.3
Output:
8.3

[edit] Icon and Unicon

At first glance you might expect the example below to run under Icon; however, as the co-expression calling sequence is Unicon specific.

Strictly speaking, genAcc(n) returns a co-expression, not a function. However, the invocation syntax here is indistinguishable from calling a function.

procedure main()
a := genAcc(3)
b := genAcc(5)
 
write(" " ,center("a",5), " ", center("b", 5))
write("genAcc: ", right(a(4),5), " ", right(b(4), 5))
write("genAcc: ", right(a(2),5), " ", right(b(3),5))
write("genAcc: ", right(a(4.5),5)," ", right(b(1.3),5))
end
 
procedure genAcc(n) # The generator factory
return makeProc { while i := (n@&source)[1] do n +:= i }
end
 
procedure makeProc(A) # A Programmer-Defined Control Operation
return (@A[1],A[1])
end

This example produces the output:

          a     b  
genAcc:     7     9
genAcc:     9    12
genAcc:  13.5  13.3

To adapt the above for use in Icon, the function-syntax for activating co-expressions (e.g. a(4)) available in Unicon would have to be replaced with the activation operator (e.g. [4]@a). The use of a list as the value passed through activation is to retain compatibility with the Unicon approach.

[edit] J

See http://www.jsoftware.com/jwiki/Guides/Lexical_Closure, including the dissent section.

oleg=:1 :0
a=. cocreate''
n__a=: m
a&(4 : 'n__x=: n__x + y')
)

Example use:

   F=: 10 oleg
F 11
21
F 12
33
F 11
44

[edit] Java

Java has no first-class functions; the standard syntactic workaround is to use a standard method name. Java uses objects to maintain state.

public class Accumulator {
private double sum;
public Accumulator(double sum0) {
sum = sum0;
}
public double call(double n) {
return sum += n;
}
 
public static void main(String[] args) {
Accumulator x = new Accumulator(1);
x.call(5);
System.out.println(new Accumulator(3));
System.out.println(x.call(2.3));
}
}
Output:
Accumulator@42e816
8.3

To do a full version that sums with integers as long as possible before switching to double-precision floats requires a little more work and the use of the Number class...

Optimized

Java has no first-class functions, but with minor syntaxical sugar it does (and yes, this will work in Java 6 and up).

import com.google.common.base.Function;
 
public class AccumulatorFactory {
private static Function<Double, Double> accumulator(final Double elem) {
return new Function<Double, Double>() {
Double sum = elem;
@Override public Double apply(Double val) {
return sum += val;
}
};
}
 
public static void main(String[] args) {
Function<Double, Double> x = accumulator(1d);
x.apply(5d);
System.out.println(accumulator(3d));
System.out.println(x.apply(2.3));
}
}
Output:
AccumulatorFactory$1@e86da0
8.3
Works with: Java version 8.0+
import java.util.function.DoubleUnaryOperator;
 
public interface AccumulatorFactory {
public static DoubleUnaryOperator accumulator(double element) {
double[] sum = new double[] { element };
return value -> sum[0] += value;
}
 
public static void main(String... arguments) {
DoubleUnaryOperator x = accumulator(1d);
x.applyAsDouble(5d);
System.out.println(accumulator(3d));
System.out.println(x.applyAsDouble(2.3));
}
}
Output:
AccumulatorFactory$$Lambda$1/2055281021@4517d9a3
8.3
Works with: Java version 5.0
public class Accumulator {
private Long sumA; // non-null if we're working in the integer domain
private double sumB;
public Accumulator(Number sum0) {
if (sum0 instanceof Double) {
sumB = sum0.doubleValue();
} else {
sumA = sum0.longValue();
}
}
public Number call(Number n) {
if (sumA != null) {
if (n instanceof Double) {
sumB = n.doubleValue() + sumA;
sumA = null;
return sumB;
}
return sumA += n.longValue();
}
return sumB += n.doubleValue();
}
 
public static void main(String[] args) {
Accumulator x = new Accumulator(1);
x.call(5);
Accumulator y = new Accumulator(3);
System.out.println(y+" has value "+y.call(0));
System.out.println(x.call(2.3));
}
}

Producing this sample output:

Accumulator@6100ab23 has value 3
8.3

[edit] JavaScript

[edit] ES5

function accumulator(sum) {
return function(n) {
return sum += n;
}
}
var x = accumulator(1);
x(5);
console.log(accumulator(3).toString() + '<br>');
console.log(x(2.3));
Output:
function (n) { return sum += n; }
8.3

[edit] ES6

let accumulator = sum => (n => sum += n);
let x = accumulator(1);
console.log(x(5));
accumulator(3);
console.log(x(2.3));
Output:
6
8.3

[edit] JavaScript 1.8 (SpiderMonkey Only)

function accumulator(sum) function(n) sum += n;
var x = accumulator(1);
x(5);
console.log(accumulator(3).toSource());
console.log(x(2.3));
Output:
(function (n) sum += n)
8.3

[edit] Julia

Using the convenient, assignment syntax for function definition:

 
function accumulator(i)
f(n) = i += n
end
x = accumulator(1)
x(5)
accumulator(3)
x(2.3)

Output

julia> function accumulator(i)
	f(n) = i += n
end
# methods for generic function accumulator
accumulator(i) at none:2

julia> x = accumulator(1)
# methods for generic function f
f(n) at none:2

julia> x(5)
6

julia> accumulator(3)
# methods for generic function f
f(n) at none:2

julia> x(2.3)
8.3

[edit] Lua

A simple implementation:

function acc(init)
init = init or 0
return function(delta)
init = init + (delta or 0)
return init
end
end

An expanded example of similar but more complex functionality:

Works with: Lua version 5.1
do
local accSum = 0; -- accumulator factory 'upvalue'
function acc(v) -- the accumulator factory
accSum = accSum + (v or 0) -- increment factory sum
 
local closuredSum = accSum; -- new 'upvalue' at each factory call
return function (w) -- the produced accumulator function
closuredSum = closuredSum + (w or 0) -- increment product 'upvalue'
return closuredSum -- return 'upvalue'
end, accSum -- end of product closure
 
end--acc
end--end of factory closure

Usage example:

x = acc(1)                 -- x stores the product with initial value = 1
x(5) -- add 5 to x's sum
acc(3) -- add 3 to factory's sum
print (x(2.3)) --> 8.3 -- add 2.3 to x's sum then print the result
y = acc() -- create new function with factory's sum as initial value
print (y()) --> 4 -- print the accumulated value inside the product y

[edit] Maple

This creates a procedure closed over the local variable total in the factory procedure. The initial value, if not passed to the factory procedure, is taken to be 0 and, if the generated accumulator is given no value, it increments the total by 1.

AccumulatorFactory := proc( initial := 0 )
local total := initial;
proc( val := 1 ) total := total + val end
end proc:

Running this, we get:

> acc := AccumulatorFactory( 1 ):
> acc( 5 );
6
 
> AccumulatorFactory( 3 ):
> acc( 2.3 );
8.3
 
> acc(); # use the default increment of 1
9.3
 
> acc( 3 - 4 * I ); # also handles complex numbers
12.3 - 4. I
 
> acc( I ); # add the imaginary unit
12.3 - 3. I

[edit] Mathematica

accFactory[initial_] := 
Module[{total = initial},
Function[x, total += x]
]
x=accFactory[1];
x[5.0];
accFactory[3];
x[2.3]
Output:
8.3

[edit] Nemerle

Nemerle doesn't have a dynamic type, but we can use matching to bind types to objects.

def Foo(n) {
mutable value : object = n;
fun (i : object) {
match(i) {
|x is int => match(value) {
|y is int => value = x + y;
|y is double => value = x + y;
}
|x is double => match(value) {
|y is int => value = x + (y :> double);
|y is double => value = x + y;
}
}
value
}
}
 
def x = Foo(1);
def y = Foo(2.2);
x(5);
System.Console.WriteLine(x(2.3));
System.Console.WriteLine(y(3));

Output:

8.3
5.2

[edit] NewLisp

(define (sum (x 0)) (inc 0 x))
 
Output:
> (define (sum (x 0)) (inc 0 x))
(lambda ((x 0)) (inc 0 x))
> (sum 1)
1
> (sum 1)
2
> (sum 1)
3
> (sum 1.4)
4.4
> (sum 1.4)
5.8
> (sum 1.8)
7.6
>

[edit] Nimrod

proc accumulator(sum: float): auto =
var sum = sum
return proc (n: float): float =
sum += n
return sum
 
var x = accumulator(1)
echo x(5) # 6
echo x(2.3) # 8.3
 
var y = accumulator(1)
echo y(5) # 6
echo y(2.3) # 8.3
 
var z = accumulator(3)
echo z(5) # 8
echo z(2.3) # 10.3
echo x(0) # 8.3
echo z(0) # 10.3

Output:

6.0000000000000000e+00
8.3000000000000007e+00
6.0000000000000000e+00
8.3000000000000007e+00
8.0000000000000000e+00
1.0300000000000001e+01
8.3000000000000007e+00
1.0300000000000001e+01

[edit] Objeck

Uses objects instead of first class functions.

bundle Default {
class Accumulator {
@sum : Float;
 
New(sum : Float) {
@sum := sum;
}
 
method : public : Call(n : Float) ~ Float {
@sum += n;
return @sum;
}
 
function : Main(args : String[]) ~ Nil {
x := Accumulator->New(1.0);
x->Call(5.0 );
x->Call(2.3)->PrintLine();
}
}
}

[edit] Objective-C

Works with: Mac OS X version 10.6+
#import <Foundation/Foundation.h>
 
typedef double (^Accumulator)(double);
 
Accumulator accumulator_factory(double initial) {
__block double sum = initial;
Accumulator acc = ^(double n){
return sum += n;
};
return acc;
}
 
int main (int argc, const char * argv[]) {
@autoreleasepool {
 
Accumulator x = accumulator_factory(1);
x(5);
accumulator_factory(3);
NSLog(@"%f", x(2.3));
 
}
return 0;
}
Output:
8.300000

[edit] OCaml

Translation of: Ruby

Deviations: An accumulator instance can take either integers or floats, but not both mixed (due to lack of runtime polymorphism).

let accumulator sum0 =
let sum = ref sum0 in
fun n ->
sum := !sum +. n;
!sum;;
 
let _ =
let x = accumulator 1.0 in
ignore (x 5.0);
let _ = accumulator 3.0 in
Printf.printf "%g\n" (x 2.3)
;;
Output:
8.3

[edit] Octave

# not a function file:
1;
function fun = foo(init)
currentSum = init;
fun = @(add) currentSum = currentSum + add; currentSum;
endfunction
 
x = foo(1);
x(5);
foo(3);
disp(x(2.3));

[edit] ooRexx

ooRexx does not have functions that can maintain state between calls. The standard work around is to use an object instance and a defined method name.

 
x = .accumulator~new(1) -- new accumulator with initial value of "1"
x~call(5)
x~call(2.3)
say "Accumulator value is now" x -- displays current value
 
-- an accumulator class instance can be instantiated and
-- used to sum up a series of numbers
::class accumulator
::method init -- instance initializer...sets the accumulator initial value
expose sum
use strict arg sum = 0 -- sets default sum value if not specified
 
-- perform the accumulator function
::method call
expose sum
use strict arg n
sum += n -- bump the accumulator
return sum -- return the new value
 
-- extra credit...display the current accumulator value
::method string
expose sum
return sum
 
 

[edit] OxygenBasic


Class AccumFactory
'=================

  double v

  method constructor()
  end method

  method destructor()
  end method

  method Accum(double n) as AccumFactory
  new AccumFactory af
  af.v=v+n
  return af
  end method

  method FloatValue() as double
  return v
  end method

  method IntValue() as sys
  return v
  end method

  method StringValue(sys dp=16) as string
  return str v,dp
  end method
 

end class

'=======================
'TESTS (all results: PI)
'=======================

new AccumFactory af

'GENERATE ACCUMULATORS

let a=af.Accum(1)   'integer
let b=a.Accum(pi)   'float
let c=b.Accum("-1") 'string

'STRING OUTPUT

print c.StringValue(4) ' show 4 decimal places

'FLOAT OUTPUT

print c.FloatValue

'USE FUNCTIONS IN EXPRESSION

print 10 * c.FloatValue() / ( 10 * a.IntValue() )

'FINISH

del af : del a : del b : del c


[edit] Oz

A bit unwieldy because the '+' operator does not allow mixed type operands. The implementation is thread-safe (atomic Exchange operation).

declare
fun {Acc Init}
State = {NewCell Init}
in
fun {$ X}
OldState
in
{Exchange State OldState} = {Sum OldState X}
end
end
 
fun {Sum A B}
if {All [A B] Int.is} then A+B
else {ToFloat A}+{ToFloat B}
end
end
 
fun {ToFloat X}
if {Float.is X} then X
elseif {Int.is X} then {Int.toFloat X}
end
end
 
X = {Acc 1}
in
{X 5 _}
{Acc 3 _}
{Show {X 2.3}}

[edit] Perl

Translation of: Ruby
sub accumulator {
my $sum = shift;
sub { $sum += shift }
}
 
my $x = accumulator(1);
$x->(5);
print accumulator(3), "\n";
print $x->(2.3), "\n";
Output:
CODE(0x91131f0)
8.3

[edit] Perl 6

Works with: Rakudo version #23 "Lisbon"
sub accum ($n is copy) { sub { $n += $^x } }

Example use:

my $a = accum 5;
$a(4.5);
say $a(.5); # Prints "10".

You can also use the "&" sigil to create a function that behaves syntactically like any other function (i.e. no sigil nor parentheses needed to call it):

my &b = accum 5;
say b 3; # Prints "8".

[edit] PHP

<?php
function accumulator($start){
return create_function('$x','static $v='.$start.';return $v+=$x;');
}
$acc = accumulator(5);
echo $acc(5), "\n"; //prints 10
echo $acc(10), "\n"; //prints 20
?>
Works with: PHP version 5.3+
<?php
function accumulator($sum){
return function ($x) use (&$sum) { return $sum += $x; };
}
$acc = accumulator(5);
echo $acc(5), "\n"; //prints 10
echo $acc(10), "\n"; //prints 20
?>

[edit] PicoLisp

(de accumulator (Sum)
(curry (Sum) (N)
(inc 'Sum N) ) )
 
(def 'a (accumulator 7))
(a 1) # Output: -> 8
(a 2) # Output: -> 10
(a -5) # Output: -> 5

[edit] PostScript

/mk-acc  {             % accumulator generator
{0 add 0 0 2 index put}
7 array copy
dup 0 4 -1 roll put
dup dup 2 exch put
cvx
} def
 
% Examples (= is a printing command in PostScript):
/a 1 mk-acc def  % create accumulator #1, name it a
5 a =  % add 5 to 1, print it
10 mk-acc  % create accumulator #2, leave it anonymous on the stack
2.71 a =  % add 2.71 to 6, print it
dup 3.14 exch exec =  % add 3.14 to 10, print it
dup 100 exch exec =  % add 100 to 13.14, print it
12 a =  % add 12 to 8.71, print it
 % accumulator #2 is still available on the stack

[edit] Prolog

Works with: SWI Prolog

Uses the module lambda written by Ulrich Neumerkel.

:- use_module(library(lambda)).
 
define_g(N, G) :-
put_attr(V, user, N),
G = V +\X^Y^(get_attr(V, user, N1),
Y is X + N1,
put_attr(V, user, Y)).
 
accumulator :-
define_g(1, G),
format('Code of g : ~w~n', [G]),
call(G, 5, S),
writeln(S),
call(G, 2.3, R1),
writeln(R1).
Output:
8 ?- accumulator.
Code of g : _G275+\_G285^_G288^ (get_attr(_G275,user,_G296),_G288 is _G285+_G296,put_attr(_G275,user,_G288))
6
8.3
true.

[edit] Python

Works with: Python version 2.x/3.x
>>> def accumulator(sum):
def f(n):
f.sum += n
return f.sum
f.sum = sum
return f
 
>>> x = accumulator(1)
>>> x(5)
6
>>> x(2.3)
8.3000000000000007
>>> x = accumulator(1)
>>> x(5)
6
>>> x(2.3)
8.3000000000000007
>>> x2 = accumulator(3)
>>> x2(5)
8
>>> x2(3.3)
11.300000000000001
>>> x(0)
8.3000000000000007
>>> x2(0)
11.300000000000001
Translation of: Ruby
Works with: Python version 3.x
def accumulator(sum):
def f(n):
nonlocal sum
sum += n
return sum
return f
 
x = accumulator(1)
x(5)
print(accumulator(3))
print(x(2.3))
Output:
<function f at 0xb7c2d0ac>
8.3
Works with: Python version 2.5+
def accumulator(sum):
while True:
sum += yield sum
 
x = accumulator(1)
x.send(None)
x.send(5)
print(accumulator(3))
print(x.send(2.3))
Output:
<generator object accumulator at 0x106555e60>
8.3

[edit] R

accumulatorFactory <- function(init) {
currentSum <- init
function(add) {
currentSum <<- currentSum + add
currentSum
}
}
Output:
> f <- accumulatorFactory(1)
> f(5)
[1] 6
> f(2.3)
[1] 8.3

[edit] Racket

#lang racket
(define ((accumulator n) i)
(set! n (+ n i))
n)
 

[edit] REBOL

make-acc-gen: func [start-val] [
use [state] [
state: start-val
func [value] [
state: state + value
]
]
]
Output:
>> x: make-acc-gen 1
>> x 5
== 6
>> make-acc-gen 3
>> print x 2.3
8.3

[edit] Retro

Retro only supports integers.

  : acc here swap , [ &+! &@ bi ] curry ;
 
( create an accumulator function )
1 acc
 
( and give it a name )
constant x
 
( add values to it and display the results )
5 x do putn
2 x do putn

[edit] REXX

This REXX program is modeled after the ooRexx example.

This example will handle any kind of number: integer, floating point.

/*REXX pgm: acculation factory copied/modeled after the ooRexx program. */
x=.accumulator(new(1)) /*set accumulater with init val 1*/
x=call(5)
x=call(2.3)
say " X value is now" x /*displays current value of X. */
say "Accumulator value is now" sum /*displays current value of accum*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────subroutines─────────────────────────*/
.accumulator: procedure expose sum
if symbol('SUM')=='LIT' then sum=0; sum=sum+arg(1)
return sum
call: procedure expose sum; sum=sum+arg(1); return sum /*adds arg1──►sum*/
new: procedure; return arg(1) /*long way 'round of using one. */

output

          X value is now 8.3
Accumulator value is now 8.3

[edit] Ruby

Ruby has methods and blocks. These are both real functions, but not with the same syntax. Our accumulator factory is a method that returns a block (in a Proc object). So, x = accumulator(1) is valid, but x(5) is an error: the syntax must be x.call(5) or x[5] (with square brackets). Ruby 1.9 also allows x.(5) (with an extra dot).

def accumulator(sum)
lambda {|n| sum += n}
end
 
# mixing Integer and Float
x = accumulator(1)
x.call(5)
p accumulator(3) # add some output to show what it returns
puts x.call(2.3) # prints 8.3
 
# mixing Rational and Complex
require 'rational'
require 'complex'
y = accumulator(Rational(2, 3))
y.call(Rational(1, 2))
puts y.call(4)
puts y.call(Complex(0, 1))
puts y.call(Complex.polar(6, 5 * Math::PI / 4))
puts x.call(0) # again prints 8.3
 
# using other things that have a + method
t = accumulator(Time.utc(1999, 8, 7, 6, 5))
puts t.call(4) # prints 1999-08-07 06:05:04 UTC
 
require 'matrix'
m = accumulator(Matrix[[1, 2], [3, 4]])
puts m.call(Matrix[[5, 6], [7, 8]])
puts t.call(-12 * 60 * 60) # subtracts 12 hours
puts y.call(1e200)
puts x.call(0) # again prints 8.3
Output:
Output from Ruby 1.8.6 Output from Ruby 1.9.2
#<Proc:0x0000000207ba7f30@/tmp/accumulator.rb:2>
8.3
31/6
31/6+1i
0.924025979547381-3.24264068711928i
8.3
Sat Aug 07 06:05:04 UTC 1999
Matrix[[6, 8], [10, 12]]
Fri Aug 06 18:05:04 UTC 1999
1.0e+200-3.24264068711928i
8.3
#<Proc:0x000002060d1788@/tmp/accumulator.rb:2 (lambda)>
8.3
31/6
31/6+1i
0.9240259795473813-3.2426406871192848i
8.3
1999-08-07 06:05:04 UTC
Matrix[[6, 8], [10, 12]]
1999-08-06 18:05:04 UTC
1.0e+200-3.2426406871192848i
8.3

[edit] Scala

The type of a function can't change in Scala, and there is no "numeric" type that is a supertype of all such types. So, if the accumulator is declared as integer, it can only receive and return integers, and so on.

def AccumulatorFactory[N](n: N)(implicit num: Numeric[N]) = {
import num._
var acc = n
(inc: N) => {
acc = acc + inc
acc
}
}
Sample:
scala> val x = AccumulatorFactory(1.0)
x: (Double) => Double = <function1>

scala> x(5.0)
res7: Double = 6.0

scala> AccumulatorFactory(3.0)
res8: (Double) => Double = <function1>

scala> println(x(2.3))
8.3

[edit] Scheme

Translation of: Ruby
(define (accumulator sum)
(lambda (n)
(set! sum (+ sum n))
sum))
 
;; or:
 
(define ((accumulator sum) n)
(set! sum (+ sum n))
sum)
 
(define x (accumulator 1))
(x 5)
(display (accumulator 3)) (newline)
(display (x 2.3)) (newline)
Output:
#<procedure>
8.3

[edit] Sidef

class Accumulator (sum) {
method add(num) {
self.sum += num;
}
}
 
var x = Accumulator(1);
x.add(5);
say Accumulator(3); # prints: Sidef::Variable::Class=HASH(0x9a80700)
say x.add(2.3); # prints: 8.3

The same thing can be achieved by using the .copy method on the block returned by the Accumulator function.

func Accumulator(sum) {
{|num| sum += num }.copy;
}
 
var x = Accumulator(1);
x.call(5);
say Accumulator(3); # prints: Sidef::Types::Block::Code=HASH(0x8bc8128)
say x.call(2.3); # prints: 8.3

[edit] Smalltalk

Works with: GNU Smalltalk
Object subclass: AccumulatorFactory [
AccumulatorFactory class >> new: aNumber [
|r sum|
sum := aNumber.
r := [ :a |
sum := sum + a.
sum
].
^r
]
]
 
|x y|
x := AccumulatorFactory new: 1.
x value: 5.
y := AccumulatorFactory new: 3.
(x value: 2.3) displayNl.
"x inspect."
"de-comment the previous line to show that x is a block closure"

the above can also be done without a class to hold the block, simply by putting it into another block:

Works with: Smalltalk/X
|factory a|
 
factory := [:initial |
[
|sum|
 
sum := initial.
[:addend | sum := sum + addend].
] value.
].
 
a := factory value:1.
a value:5.
factory value:3.
(a value:2.3) printCR "-> 8.3 "

[edit] Standard ML

Translation of: OCaml

Deviations: An accumulator instance can take either integers or reals, but not both mixed (due to lack of runtime polymorphism).

fun accumulator (sum0:real) : real -> real = let
val sum = ref sum0
in
fn n => (
sum := !sum + n;
 !sum)
end;
 
let
val x = accumulator 1.0
val _ = x 5.0
val _ = accumulator 3.0
in
print (Real.toString (x 2.3) ^ "\n")
end;
Output:
8.3

[edit] Swift

func makeAccumulator(var sum: Double) -> Double -> Double {
return {
sum += $0
return sum
}
}
 
let x = makeAccumulator(1)
x(5)
let _ = makeAccumulator(3)
println(x(2.3))
Output:
8.3

[edit] Tcl

Works with: Tcl version 8.6

This uses nested coroutines to manage the state, which for the outer coroutine is a counter used to generate unique instances of the inner coroutine, and for the inner coroutine it is the actual accumulator variable. Note that Tcl commands (including coroutines) are never nameless, but it is trivial to synthesize a name for them. It's possible to guarantee uniqueness of names, but just using a simple sequence generator gets 90% of the effect for 10% of the effort.

package require Tcl 8.6
 
# make the creation of coroutines without procedures simpler
proc coro {name arguments body args} {
coroutine $name apply [list $arguments $body] {*}$args
}
# Wrap the feeding of values in and out of a generator
proc coloop {var body} {
set val [info coroutine]
upvar 1 $var v
while 1 {
set v [yield $val]
if {$v eq "stop"} break
set val [uplevel 1 $body]
}
}
 
# The outer coroutine is the accumulator factory
# The inner coroutine is the particular accumulator
coro accumulator {} {
coloop n {
coro accumulator.[incr counter] n {
coloop i {
set n [expr {$n + $i}]
}
} $n
}
}

Sample usage (extra characters over Paul's example to show more clearly what is going on):

% set x [accumulator 1]
::accumulator.1
% $x 5
6
% accumulator 3
::accumulator.2
% puts ">>[$x 2.3]<<"
>>8.3<<

[edit] Unicon

Strictly speaking, genAcc(n) returns a co-expression, not a function. However, the invocation syntax here is indistinguishable from calling a function.

procedure main()
a := genAcc(3)
b := genAcc(5)
 
write(" " ,center("a",5), " ", center("b", 5))
write("genAcc: ", right(a(4),5), " ", right(b(4), 5))
write("genAcc: ", right(a(2),5), " ", right(b(3),5))
write("genAcc: ", right(a(4.5),5)," ", right(b(1.3),5))
end
 
procedure genAcc(n) # The generator factory
return makeProc { while i := (n@&source)[1] do n +:= i }
end
 
procedure makeProc(A) # A Programmer-Defined Control Operation
return (@A[1],A[1])
end

Note: The co-expression calling sequence used is Unicon specific.

Output:
          a     b  
genAcc:     7     9
genAcc:     9    12
genAcc:  13.5  13.3

[edit] TXR

[edit] Verbose

@(do
(defun accumulate (sum)
(lambda (n)
(inc sum n)))
 
 ;; test
(for ((f (accumulate 0))
num)
((set num (read)))
((format t "~s -> ~s\n" num [f num])))
 
(exit 0))

Run:

$ txr accumulator-factory.txr
1
1 -> 1
2
2 -> 3
3
3 -> 6
400000000000000000000000000000000000000000000000000000000000000000000000
400000000000000000000000000000000000000000000000000000000000000000000000 -> 400000000000000000000000000000000000000000000000000000000000000000000006
5.3
5.3 -> 4e71
1e71
1e71 -> 5e71
[Ctrl-D][Enter]
$

[edit] Slick

@(do (let ((f (let ((sum 0)) (do inc sum @1))))
(mapdo (op format t "~s -> ~s\n" @1 [f @1]) (gun (read)))))
Output:
$ echo "1 2 3 4.5" | txr accumulator-factory2.txr 
1 -> 1
2 -> 3
3 -> 6
4.5 -> 10.5

[edit] UNIX Shell

Deviation from task: The accumulator factory returns a global function, which stores the sum in a global variable. Other code can modify the function or the variable, perhaps by accident.

The shell is a bad choice for this task. This example plays tricks with eval. The difficulty with eval is to put the quotation marks " and dollar signs $ in the correct place, and escape them with the correct number of backslashes \. One missing (or one extra) backslash can ruin the entire program.

Works with: pdksh
#!/bin/sh
accumulator() {
# Define a global function named $1
# with a global variable named ${1}_sum.
eval "${1}_sum=\$2"
eval "$1() {
${1}_sum=\$(echo \"(\$${1}_sum) + (\$2)\" | bc)
eval \"\$1=\\\$${1}_sum\" # Provide the current sum.
}"

}
 
accumulator x 1
x r 5
accumulator y 3
x r 2.3
echo $r
y r -3000
echo $r
Output:
$ sh accumulator.sh
8.3
-2997

[edit] es

A better shell for this task is es, because it has lexical variables and closures. @ i {code} is a lambda with parameter i, and fn accumulator n {code} is sugar for fn-accumulator = @ n {code}.

fn accumulator n {
result @ i {
n = `{echo $n + $i | bc}
result $n
}
}
 
fn-x = <={accumulator 1}
x 5
fn-y = <={accumulator 3}
echo <={x 2.3}
echo <={y -3000}

[edit] VBScript

I'm not entirely convinced that this is actually doing what is asked. A VBScript guru I'm not. The answer's right, though.

Implementation
class accumulator
dim A
public default function acc(x)
A = A + x
acc = A
end function
public property get accum
accum = A
end property
end class
Invocation
dim a
set a = new accumulator
x = a( 1 )
a 5
dim b
set b = new accumulator
b 3
wscript.echo a(2.3)
Output:
8.3

[edit] Wart

def (accumulator n)
(fn() ++n)

Example usage:

a <- (accumulator 3)
(a)
=> 4
(a)
=> 5
b <- (accumulator 23)
(b)
=> 24
(a)
=> 6

[edit] Yorick

Yorick cannot dynamically create new functions. Instead, the accum function can be called in two ways: directly, in which case its first argument is numerical; or through a closure, where its first argument is implicitly an object and the second is the user-provided argument. This example uses closures and group objects, which require Yorick 2.2 or later.

func accum(data, n) {
if(!is_obj(data))
return closure(accum, save(total=data));
save, data, total=data.total + n;
return data.total;
}

Example of use (interactive session):

> x = accum(1)
> x(5)
6
> y = accum(3)
> x(2.3)
8.3
> y(2.3)
5.3

[edit] zkl

fcn foo(n){fcn(n,acc){acc.set(n+acc.value).value}.fp1(Ref(n))}

A strong reference (Ref) is used as the accumulator, a Ref acts like a one element list. The Ref is bound to the new functions second parameter with the .fp1 method.

x:=foo(1)   //--> partially applied function
x(5)       //-->6 (int)
y:=foo(3) //-->new PFA
x(2.3).println()
8.3

x(2)  //-->10 (int)
y(2) //-->5 (int)

The output switches between int and float based on the most recent input: With addition, the first operand casts the second: int + int|float --> int and float + int|float --> float. If the desire is to make the behavior "once float, always float", a 0 or 0.0 can be used to start the sum and stashed in a another bit of state.

Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox