Accumulator factory: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
m (→‎{{header|Java}}: formatting)
Line 56: Line 56:
=={{header|Java}}==
=={{header|Java}}==
Java has no first-class functions. Java uses objects to maintain state.
Java has no first-class functions. Java uses objects to maintain state.
<lang python>public class Accumulator {
<lang java>public class Accumulator {
private double sum;
private double sum;
public Accumulator(double sum0) {
public Accumulator(double sum0) {

Revision as of 23:21, 29 December 2009

Accumulator factory is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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.

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.)
  3. Generates functions that return the sum of every number ever passed to them, not just the most recent.
  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.
  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.
E.g. if after the example, you added the following code (in a made-up language):
<lang pseudocode>x = foo(1);

x(5); foo(3); print x(2.3);</lang>

It should print 8.3.

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.

E

<lang e>def foo(var x) {

 return fn y { x += y }

}</lang>

Factor

<lang factor>:: accumulator ( n! -- quot ) [ n + dup n! ] ;

1 accumulator [ 5 swap call drop ] [ drop 3 accumulator drop ] [ 2.3 swap call ] tri .</lang>

Haskell

Translation of: Ruby

<lang haskell>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</lang>

outputs

8.3

Java

Java has no first-class functions. Java uses objects to maintain state. <lang java>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));
   }

}</lang> outputs

Accumulator@42e816
8.3

JavaScript

Translation of: Ruby
Works with: SpiderMonkey

<lang javascript>function accumulator(sum) {

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

}

x = accumulator(1); x(5); print(accumulator(3)); print(x(2.3));</lang>

output

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

OCaml

Translation of: Ruby

<lang ocaml>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)
</lang>

outputs

8.3

Perl

Translation of: Ruby

<lang perl>sub accumulator {

 my $sum = shift;
 sub { $sum += shift }

}

my $x = accumulator(1); $x->(5); print accumulator(3), "\n"; print $x->(2.3), "\n";</lang> outputs

CODE(0x91131f0)
8.3

Perl 6

Works with: Rakudo version #23 "Lisbon"

<lang perl6>sub accum ($n is copy) { sub { $n += $^x } }</lang>

Example use:

<lang perl6>my $a = accum 5; $a(4.5); say $a(.5); # Prints "10".</lang>

Python

Translation of: Ruby
Works with: Python version 3.x

<lang python>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))</lang> outputs

<function f at 0xb7c2d0ac>
8.3

Ruby

Add some output to the 2nd call to "accumulator" to show what it returns <lang ruby>def accumulator(sum)

 lambda {|n| sum += n}

end

x = accumulator(1) x.call(5) p accumulator(3) puts x.call(2.3)</lang> outputs

#<Proc:0x1002f14c@accumulator.rb:5>
8.3

Scheme

Translation of: Ruby

<lang scheme>(define (accumulator sum)

 (lambda (n)
   (set! sum (+ sum n))
   sum))

(define x (accumulator 1)) (x 5) (display (accumulator 3)) (newline) (display (x 2.3)) (newline)</lang> outputs

#<procedure>
8.3

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. <lang tcl>package require Tcl 8.6

  1. make the creation of coroutines without procedures simpler

proc coro {name arguments body args} {

   coroutine $name apply [list $arguments $body] {*}$args

}

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

   }

}

  1. The outer coroutine is the accumulator factory
  2. The inner coroutine is the particular accumulator

coro accumulator {} {

   coloop n {

coro accumulator.[incr counter] n { coloop i { set n [expr {$n + $i}] } } $n

   }

}</lang> Sample usage (extra characters over Paul's example to show more clearly what is going on): <lang tcl>% set x [accumulator 1]

accumulator.1

% $x 5 6 % accumulator 3

accumulator.2

% puts ">>[$x 2.3]<<" >>8.3<<</lang>