Jump to content

Accumulator factory: Difference between revisions

Replace existing solution by a more general one and add a solution using a customized number type.
(Replace existing solution by a more general one and add a solution using a customized number type.)
Line 2,121:
 
=={{header|Nim}}==
Nim being a static typed language, if the accumulator function was created with an integer, it will always return an integer. So, it isn’t possible to mix integers and float.
<lang nim>proc accumulator(sum: float): auto =
Three solutions are possible:
var sum = sum
:– convert returnall procvalues (n:to float): float =;
:– give the accumulator type the type of the initial value provided at the creation;
sum += n
:– use a customized type.
return sum
We provide the code for the two last solutions.
 
var x ==={{Fixed accumulator(1) type}}===
<lang Nim>
echo x(5) # 6
proc accumulator[T: SomeNumber](x: T): auto =
echo x(2.3) # 8.3
var sum = x
result = proc (n: T): T =
sum += n
result = sum
 
varlet yx = accumulator(1)
echo yx(5) # 6
echo yx(2.3) # 8.3
let y = accumulator(3.5)
echo y(2) # 5.5
echo y(3) # 8.5
</lang>
{{out}}
<pre>
6
8
5.5
8.5
</pre>
 
==={Customized number typed}===
var z = accumulator(3)
<lang Nim>
echo z(5) # 8
type
echo z(2.3) # 10.3
 
echo x(0) # 8.3
# Kind of numbers. We limit this example to "int" and "float".
echo z(0) # 10.3</lang>
NumberKind = enum kInt, kFloat
Output:
 
<pre>6.0000000000000000e+00
# Customized number type (using variants).
8.3000000000000007e+00
Number = object
6.0000000000000000e+00
case kind: NumberKind
8.3000000000000007e+00
of kInt: ival: int
8.0000000000000000e+00
of kFloat: fval: float
1.0300000000000001e+01
 
8.3000000000000007e+00
# The converters allow transparent conversion from int or float to Number.
1.0300000000000001e+01</pre>
converter toNumber(n: int): Number = Number(kind: kInt, ival: n)
converter toNumber(n: float): Number = Number(kind: kFloat, fval: n)
 
#---------------------------------------------------------------------------------------------------
 
proc accumulator[T: int|float](x: T): auto =
## Factory procedure.
 
# Allocate the accumulator storage.
when T is int:
var sum = Number(kind: kInt, ival: x)
elif T is float:
var sum = Number(kind: kFloat, fval: x)
 
# Create the accumulator procedure.
result = proc (n: Number): Number =
case sum.kind
of kInt:
case n.kind
of kInt:
# Add an int to an int.
sum.ival += n.ival
of kFloat:
# Add a float to an int => change the kind of accumulator to float.
sum = Number(kind: kFloat, fval: sum.ival.toFloat + n.fval)
of kFloat:
case n.kind
of kInt:
# Add an int to a float.
sum.fval += n.ival.toFloat
of kFloat:
# Add a float to a float.
sum.fval += n.fval
result = sum
 
#---------------------------------------------------------------------------------------------------
 
proc `$`(n: Number): string =
## Display the accumulator contents as an int or a float depending of its kind.
case n.kind
of kInt: $n.ival
of kFloat: $n.fval
 
#---------------------------------------------------------------------------------------------------
 
let acc = accumulator(1)
echo acc(5) # 6
discard accumulator(3) # Create another accumulator.
echo acc(2.3) # 8.3
</lang>
 
{{out}}
<pre>
6
8.300000000000001
</pre>
 
=={{header|Nit}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.