![]() |
Office 2010 Professional Accumulator factory - Ros
Accumulator factory
You're encouraged to unravel this job according for the process description, employing any language you could possibly know. From Rosetta Code A dilemma posed by Paul Graham is always that of developing a function that will take a single (numeric) argument and which returns one more purpose that is an accumulator. The returned accumulator perform in turn also can take a single numeric argument, and returns the sum of all the numeric values handed in thus far to that accumulator (such as the initial worth handed when the accumulator was designed). The thorough guidelines are at and therefore are reproduced here for simplicity (with additions in tiny italic text). Ahead of you submit an instance, be sure the perform Requires a amount n and returns a operate (lets get in touch with it g), that requires a range i, and returns n incremented through the accumulation of i from each get in touch with of purpose g(i). Although these precise perform and parameter names want not be utilized Operates for any numeric type-- i.e. can consider each ints and floats and returns features that may consider the two ints and floats. (It is not ample just to convert all input to floats. An accumulator that has only seen integers must return integers.) (i.e., if your language doesn't allow for numeric polymorphism, you've got to make use of overloading or one thing like that) Generates features that return the sum of every amount actually passed to them, not just probably the most current. (This needs a bit of state to carry the accrued value, which in turn means that pure purposeful languages cannot be employed for this job.) Returns a true perform, meaning some thing which you can use wherever you could use a function you had defined in the ordinary way within the text of the method. (Stick to your language's conventions here.) Does not keep the accumulated value or the returned capabilities in a very way that can result in them to be inadvertantly modified by other code. (No worldwide variables or other this kind of items.) E.g. if after the instance, you extra the following code (inside a made-up language) in which the factory operate is known as foo: x = foo(1); x(five); foo(three); print x(2.three); It ought to print 8.3. (There exists no will need to print the type of the accumulator function returned by foo(three); it's not component with the activity at all.) The purpose of this task would be to develop a perform that implements the explained rules. It will need not deal with any specific error instances not explained previously mentioned. The simplest approach to put into action the job as described is usually to use a closure, providing the language supports them. Where it isn't achievable to hold precisely towards the constraints over, explain the deviations. one ABAP 1.one Object Oriented Solution one.two JavaScript Solution two ActionScript three Aikido 4 ALGOL 68 five Argile six Brat seven C++ 8 C# 9 Clojure 10 Widespread Lisp 11 D 12 E thirteen Elena 14 Aspect fifteen Fantom 16 Forth 17 F# eighteen GAP 19 Go twenty Groovy 21 Haskell 22 Icon and Unicon 23 J 24 Java twenty five JavaScript 26 Lua 27 Mathematica 28 Objeck 29 Objective-C thirty OCaml 31 Oz 32 Perl 33 Perl six 34 PHP 35 PicoLisp 36 PostScript 37 Python 38 R 39 REBOL forty Retro 41 Ruby 42 Scala 43 Scheme 44 Smalltalk 45 Tcl 46 Unicon 47 UNIX Shell 48 VBScript 49 Yorick [edit] ABAP ABAP, sadly, has no 1st buy functions, nor does its OO paradigm put into action strategy overloading. A single possible remedy to this problem is always to use classes to maintain the state, using the import/export parameters being defined as sort 'any', so that the resultant kind is calculated dynamically. Another doable resolution will be to use the languages in-built JavaScript processing abilities to dynamically build a JS supply at run-time, which implements the JS Accumulator factory. [edit] Object Oriented Answer report z_accumulator class acc definition. general public segment. techniques: call importing iv_i variety any default 0 exporting ev_r sort any, constructor importing iv_d variety f. non-public segment. knowledge a_sum type f. endclass. class acc implementation. technique contact. add iv_i to a_sum. ev_r = a_sum. endmethod. start-of-selection. data: cl_acc sort ref to acc, lv_ret2 type f, lv_ret1 sort i. create object cl_acc exporting iv_d = one. 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 = two importing ev_r = lv_ret1 ). write : / lv_ret2 decimals 2 exponent 0 left-justified, / lv_ret1 left-justified. eight.30 ten [edit] JavaScript Solution data: lv_source type string, cl_processor variety ref to cl_java_script, lv_ret kind 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(two.three);' 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.three [edit] ActionScript Closures work the same in ActionScript as in JavaScript. ActionScript will transparently convert integers to reals when the function is given a real argument,Buy Windows 7, but the typeof operator must be utilized to ensure the purpose isn't sent invalid arguments, this kind of as strings (which would silently convert the accumulated quantity to a string without throwing an error). //Throw an error if a non-number argument is utilized. (typeof evaluates to // "number" for each integers and reals) function checkType(obj:Object):void { if(typeof obj ,Office Pro Plus 2007!= "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 get thrown. [edit] Aikido function accumulator (sum:actual) { return function(n:real) return sum += n } var x = accumulator(one) x(5) println (accumulator) println (x(2.3)) Output: accumulator 8.three [edit] ALGOL 68 Note: Standard ALGOL 68's scoping policies forbids exporting a procedure (or format) out of it can be scope (closure). Hence this specimen will operate on ELLA ALGOL 68, but is non-standard. For a discussion of first-class capabilities in ALGOL 68 consult "The Making of Algol 68" - C.H.A. Koster (1993). MODE Number = UNION(INT,Real,COMPL); PROC plus = (Amount within a, in b)Quantity: ( CASE in a very IN (INT a): CASE in b IN (INT b): a+b, (Actual b): a+b, (COMPL b): a+b ESAC, (Actual a): CASE in b IN (INT b): a+b, (Genuine b): a+b, (COMPL b): a+b ESAC, (COMPL a): CASE in b IN (INT b): a+b, (Actual b): a+b, (COMPL b): a+b ESAC ESAC ); main: ( # now override the + and +:= OPerators # OP + = (Quantity a, b)Quantity: plus(a,b); OP +:= = (REF Number lhs, Quantity rhs)Quantity: lhs := lhs + rhs; PROC accumulator = (REF Range sum)PROC(NUMBER)Range: (Number n)Amount: sum +:= n; PROC (NUMBER)Number x = accumulator(LOC Amount := 1); x(5); print(("x:",x(two.3), new line)); PROC (NUMBER)Quantity y = accumulator(LOC Range := 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] Argile use std, array let A = accumulator 42 print(A 0) print(A 1) print(A 10) print(A 100) let B = accumulator four.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) get in touch with ((a.func) as operate(any)(a.t)->(a.t)) with (a.info) ((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 <actual x> :. -> true accumulator (val (genuine accumulator) A).init(x) (A as Accumulator).func = ( .:<real&accu,actual x>:. ->genuineaccu += x; accu ) A =: <accumulator& a>.init <num x> := a = new (Accumulator) a.information = (new array of one 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] Brat accumulator = { sum | n } x = accumulator 1 x 5 accumulator 3 #Does not affect x p x 2.3 #Prints eight.three (1 + 5 + two.three) [edit] C++ Deviation: The return variety is wrong once the accumulator is called with an integer argument soon after is has been known as 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] C# 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(two.3)); } } [edit] Clojure The atom perform creates an atomically updatable identity holding a appeal. The swap! function atomically updates the atom's appeal, returning the new price. The operate returned from an accum get in touch with satisfies every one of 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] Common Lisp (defun accumulator (sum) (lambda (n) (setf sum (+ sum n)))) Example usage: (defvar x (accumulator 1)) (funcall x 5) (accumulator 3) (funcall x two.3) This prints: X 6 #<CLOSURE :LAMBDA (N) (SETF SUM (+ SUM N))> 8.three [edit] D auto acc(U = genuine, T)(T initvalue) { // U is variety with the accumulator auto accum = cast(U)initvalue ; return (U n) { return accum += n ; } ; } [edit] E def foo(var x) { return fn y { x += y } } [edit] Elena #define basic'* = std'basic'*. #symbol AccumulatorFactory = { new : aValue [ #var anAccumulator := basic'Variable::aValue. ^ #annex(anAccumulator) evaluate : aValue [ anAccumulator new:(aValue + anAccumulator). ] . ] }. #symbol Plan => [ #var x := AccumulatorFactory new:one. x evaluate:5. AccumulatorFactory new:3. 'program'Output << x evaluate:2.3r. ]. [edit] Element :: accumulator ( n! -- quot ) [ n + dup n! ] ; 1 accumulator [ 5 swap call drop ] [ drop three accumulator drop ] [ 2.three swap call ] tri . [edit] Fantom The accumulator purpose is a little unwieldy employing multiple ifs to take care of the type of 'sum' until forced to change. Again, a result from the three concrete Num types, Int, Float and Decimal, all currently being separated inside 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 functions on integers. : accumulator generate ( n -- ) , does> ( n -- acc+n ) tuck +! @ ; 0 accumulator foo 1 foo . \ 1 2 foo . \ 3 3 foo . \ 6 [edit] F# A statically typed version just isn't 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 variety 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 three |> ignore printfn "%A" (x two.3) // prints "8.3" [edit] GAP accu := operate(n) local f, v; v := n; f := perform(a) v := v + a; return v; end; return f; end; a := accu(0); # function( a ) ... end b := accu(100); # purpose( a ) ... end a(six); # 6 b(6); # 106 a(1); # 7 b(one); # 107 # These capabilities also accept other types,Office 2010 Professional, 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 Deviations: This does not fulfill condition 2. The result is a float even if you only use integers. package main import "fmt" func accumulator(sum float64) func(float64) float64 { return func (n float64) float64 sum += n return sum } func main() x := accumulator(1.0) x(5.0) accumulator(3.0) fmt.Printf("%g\n", x(2.3)) outputs 8.3 [edit] Groovy Solution: def accumulator = { Quantity 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(two.3) assert x() instanceof BigDecimal println y(10) assert y() instanceof Integer println y(200L) assert y() instanceof Long println y(two.25D) assert y() instanceof Double Output: 1 six 3 eight.three 13 213 215.25 [edit] Haskell import Control.Monad.ST import Information.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 wherever foo = runST $ do x <- accumulator 1 x 5 accumulator 3 x 2.3 outputs 8.3 [edit] Icon and Unicon At 1st glance you might expect the illustration 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 operate. However, the invocation syntax right here is indistinguishable from calling a purpose. procedure main() a := genAcc(3) b := genAcc(5) write(" " ,center("a",Microsoft Office Home And Student 2010,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(four.5),5)," ", right(b(one.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: seven 9 genAcc: 9 twelve genAcc: 13.5 13.three show Icon co-expression calling sequence as a note. [edit] J See which includes the dissent part. oleg=:1 :0 a=. cocreate'' n__a=: m a&(4 : 'n__x=: n__x + y') ) Example use: F=: ten oleg F 11 21 F 12 33 F 11 44 [edit] Java Java has no first-class capabilities; the standard syntactic workaround is usually to use a standard method name. Java uses objects to maintain state. public class Accumulator { personal double sum; general 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(two.3)); } } outputs Accumulator@42e816 8.3 To do a full version that sums with integers as long as achievable ahead of switching to double-precision floats demands a little more work and the use of the Range 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.typical.base.Purpose; 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 public class Accumulator { private Long sumA; // non-null if we're working inside the integer domain personal double sumB; general public Accumulator(Amount sum0) { if (sum0 instanceof Double) { sumB = sum0.doubleValue(); } else { sumA = sum0.longValue(); } } public Range 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(); } general public static void main(String[] args) { Accumulator x = new Accumulator(1); x.call(5); Accumulator y = new Accumulator(3); System.out.println(y+" has price "+y.call(0)); System.out.println(x.call(2.3)); } } Producing this sample output: Accumulator@6100ab23 has appeal 3 8.three [edit] JavaScript function accumulator(sum) { return function(n) { return sum += n; } } var x = accumulator(1); x(5); document.write(accumulator(3).toString() + '<br>'); document.write(x(two.3)); output function (n) return sum += n; eight.3 function accumulator(sum) function(n) sum += n; var x = accumulator(1); x(5); console.log(accumulator(3).toSource()); console.log(x(2.3)); output (perform (n) sum += n) 8.three [edit] Lua 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 illustration: x = acc(1) -- x stores the product with preliminary price = 1 x(5) -- add five to x's sum acc(3) -- add 3 to factory's sum print (x(two.3)) --> 8.three -- add two.three to x's sum then print the result y = acc() -- generate new purpose with factory's sum as initial value print (y()) --> four -- print the accumulated worth inside the product y [edit] Mathematica accFactory[initial_] := Module[total = initial, Function[x, total += x] ] x=accFactory[1]; x[5.0]; accFactory[3]; x[2.3] outputs 8.3 [edit] Objeck Uses objects instead of very first class functions. bundle Default { class Accumulator { @sum : Float; New(sum : Float) { @sum := sum; } method : general public : Call(n : Float) ~ Float { @sum += n; return @sum; } purpose : Main(args : String[]) ~ Nil { x := Accumulator->New(1.0); x->Call(5.0 ); x->Call(2.3)->PrintLine(); } } } [edit] Objective-C #import <Foundation/Foundation.h> typedef double (^Accumulator)(double); Accumulator accumulator_factory(double initial) { __block double sum = preliminary; Accumulator acc = ^(double n){ return sum += n; }; return [[acc copy] autorelease]; } int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Accumulator x = accumulator_factory(1); x(5); accumulator_factory(3); NSLog(@"%f", x(2.3)); [pool drain]; return 0; } outputs 8.300000 [edit] OCaml Deviations: An accumulator instance can take either integers or floats, but not the two 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 three.0 in Printf.printf "%g\n" (x two.3) ;; outputs 8.three [edit] Oz A bit unwieldy because the '+' operator does not enable mixed variety 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 five _} {Acc three _} {Show {X 2.3}} [edit] Perl sub accumulator { my $sum = shift; sub { $sum += shift } } my $x = accumulator(1); $x->(5); print accumulator(3), "\n"; print $x->(two.3), "\n"; outputs CODE(0x91131f0) 8.3 [edit] Perl six sub accum ($n is copy) { sub { $n += $^x } } Example use: my $a = accum 5; $a(four.5); say $a(.5); # Prints "10". You can also utilize the "&" sigil to build a operate that behaves syntactically like any other purpose (i.e. no sigil nor parentheses needed to call it): my &b = accum 5; say b 3; # Prints "8". [edit] PHP <? function accumulator($start){ return create_function('$x','static $v='.$start.';return $v+=$x;'); } $acc=accumulator(5); echo $acc(5); //prints 10 echo $acc(10); //prints 20 ?> [edit] PicoLisp (de accumulator (Sum) (curry (Sum) (N) (inc 'Sum N) ) ) (def 'a (accumulator seven)) (a 1) # Output: -> 8 (a two) # Output: -> 10 (a -5) # Output: -> five [edit] PostScript /mk-acc { % accumulator generator 0 add 0 0 2 index put 7 array copy dup 0 four -1 roll put dup dup 2 exch put cvx } def % Examples (= is a printing command in PostScript): /a 1 mk-acc def % develop accumulator #1, name it a 5 a = % add 5 to 1, print it 10 mk-acc % generate 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,Microsoft Office Ultimate 2007, print it 12 a = % add twelve to eight.71, print it % accumulator #2 is still available on the stack [edit] Python >>> 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(two.3) 8.3000000000000007 >>> x2 = accumulator(3) >>> x2(5) 8 >>> x2(three.3) 11.300000000000001 >>> x(0) 8.3000000000000007 >>> x2(0) 11.300000000000001 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] R accumulatorFactory <- purpose(init) { currentSum <- init function(add) currentSum <<- currentSum + add currentSum } outputs > f <- accumulatorFactory(1) > f(five) [1] six > f(2.three) [1] eight.three [edit] REBOL make-acc-gen: func [start-val] [ use [state] [ state: start-val func [value] [ state: state + value ] ] ] outputs >> x: make-acc-gen one >> x 5 == six >> make-acc-gen 3 >> print x 2.three 8.three [edit] Retro Retro only supports integers. : acc here swap , [ &+! &@ bi ] curry ; ( produce an accumulator operate ) one acc ( and give it a name ) constant x ( add values to it and display the results ) five x do putn 2 x do putn [edit] Ruby Ruby has methods and blocks. These are equally real features, but not with the same syntax. Our accumulator factory is a approach that returns a block (in a Proc object). So, x = accumulator(one) is valid, but x(five) is surely an error: the syntax must be x.phone(five) or x[5] (with square brackets). Ruby one.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(two.3) # prints eight.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(six, five * Math::PI / 4)) puts x.call(0) # again prints 8.3 # utilizing other things that have a + method t = accumulator(Time.utc(1999, eight, 7, six, 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 eight.three Output from Ruby 1.8.6 Output from Ruby one.nine.two #<Proc:0xba7f30@/tmp/accumulator.rb:2> 8.three 31/6 31/6+1i 0.924025979547381-3.24264068711928i eight.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 eight.three #<Proc:0x000002060d1788@/tmp/accumulator.rb:two (lambda)> 8.three 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 eighteen:05:04 UTC one.0e+200-3.2426406871192848i eight.3 [edit] Scala The kind of a operate can not change in Scala, and there exists no "numeric" sort that is certainly a supertype of all this sort of types. So, if your 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(one.0) x: (Double) => Double = <function1> scala> x(five.0) res7: Double = six.0 scala> AccumulatorFactory(three.0) res8: (Double) => Double = <function1> scala> println(x(two.three)) eight.3 [edit] Scheme (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 two.3)) (newline) outputs #<procedure> eight.three [edit] 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 appeal: 5. y := AccumulatorFactory new: 3. (x worth: two.3) displayNl. "x inspect." "de-comment the previous line to show that x is a block closure" [edit] Tcl This uses nested coroutines to manage the state, which for the outer coroutine is a counter utilized to generate unique instances with the inner coroutine, and for the inner coroutine it is the actual accumulator variable. Note that Tcl commands (which includes coroutines) are never nameless, but it really is trivial to synthesize a name for them. It really is possible to guarantee uniqueness of names, but just employing a simple sequence generator gets 90% from the effect for 10% with the effort. package require Tcl eight.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 one $var v while one { set v [yield $val] if {$v eq "stop"} break set val [uplevel one $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 instance 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 operate. However, the invocation syntax here is indistinguishable from calling a operate. 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(four.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 utilised is Unicon specific. This illustration produces the output: a b genAcc: 7 nine genAcc: 9 12 genAcc: thirteen.5 thirteen.3 [edit] UNIX Shell Deviation from task: The accumulator factory returns a worldwide perform, which stores the sum inside a global variable. Other code can modify the purpose or the variable, perhaps by accident. The shell is a bad choice for this activity. This illustration plays tricks with eval. The difficulty with eval is to put the quotation marks " and dollar signs $ from the correct place, and escape them together with the correct quantity of backslashes \. One missing (or 1 extra) backslash can ruin the entire system. #!/bin/sh accumulator() { # Define a worldwide perform named $1 # with a world-wide 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] 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 purpose 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(two.three) Output 8.3 [edit] Yorick Yorick cannot dynamically develop new functions. Instead, the accum perform can be named in two ways: directly, in which case its initial argument is numerical; or through a closure, exactly where its 1st argument is implicitly an object and the second is the user-provided argument. This illustration uses closures and group objects, which require Yorick 2.two or later. func accum(knowledge, 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(one) > x(5) six > y = accum(3) > x(two.3) eight.three > y(2.3) five.3 |
All times are GMT. The time now is 03:01 PM. |
Powered by vBulletin Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Free Advertising Forums | Free Advertising Message Boards | Post Free Ads Forum