Accumulator factory

From Rosetta Code

Jump to: navigation, search
Accumulator factory is a programming task. Visitors like you are encouraged to solve it according to the task description, using any language they may happen to know.
Add to BlogMarksAdd to del.icio.usAdd to diggAdd to NewsvineAdd to redditAdd to Slashdot

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, and returns functions that take, exactly one argument.
  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 inadvertantly 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] 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] 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.

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(int argc, char* argv[])
{
Acc a(1);
a(5);
Acc(3);
std::cout << a(2.3f);
return 0;
}

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

[edit] Common Lisp

(defun accumulator (sum)
(lambda (n)
(setf sum (+ sum n))))

Example usage:

(defvar x (accumulator 1))
(funcall x 5)
(accumulator 3)
(funcall x 2.3)

This prints:

X
6
#<CLOSURE :LAMBDA (N) (SETF SUM (+ SUM N))>
8.3

[edit] E

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

[edit] Factor

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

[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] 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

outputs

8.3

[edit] J

See http://www.jsoftware.com/jwiki/Guides/Lexical_Closure

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

[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));
}
}

outputs

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

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

Translation of: Ruby

Works with: SpiderMonkey

function accumulator(sum) {
return function(n) {return sum += n}
}
 
x = accumulator(1);
x(5);
print(accumulator(3));
print(x(2.3));

output

function (n) {
    return sum += n;
}
8.3

[edit] OCaml

Translation of: Ruby

let accumulator sum0 =
let sum = ref sum0 in
fun n ->
sum := !sum +. n;
!sum
 
let () =
let x = accumulator 1.0 in
x 5.0;
accumulator 3.0; (* generates a warning because we are discarding a non-unit value *)
Printf.printf "%g\n" (x 2.3)
;;

outputs

8.3

[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";

outputs

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

[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] 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))

outputs

<function f at 0xb7c2d0ac>
8.3

[edit] REBOL

 
make-acc-gen: func [start-val] [
func [value /local state] compose/deep [
state: [(start-val)]
state/1: state/1 + value
state/1
]
]
 
outputs
>> x: make-acc-gen 1
>> x 5
== 6
>> make-acc-gen 3
>> print x 2.3
8.3

[edit] Ruby

Add some output to the 2nd call to "accumulator" to show what it returns

def accumulator(sum)
lambda {|n| sum += n}
end
 
x = accumulator(1)
x.call(5)
p accumulator(3)
puts x.call(2.3)

outputs

#<Proc:0x1002f14c@accumulator.rb:5>
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)

outputs

#<procedure>
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] 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.

[edit] 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
[edit] 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)
[edit] Output
8.3
Personal tools
Google AdSense