Jump to content

Loops/With multiple ranges: Difference between revisions

Line 1,379:
prod=-793618560
</pre>
 
=={{header|Nim}}==
Nim doesn’t provide loops with multiple ranges. There are several ways to translate the PL/1 program: using a sequence of for loops, using a sequence of while loops, using an iterator and, probably, too, some way using macros.
 
===Using a sequence of loops===
This solution is the obvious one, but it supposes that the direction of the loop is known (i.e. the sign of the step is known) as we have to choose between iterators “countup” and “countdown”. Using this method, the PL/1 example can be translated the following way:
 
<lang Nim>
import math, strutils
 
var
prod = 1
sum = 0
 
let
x = +5
y = -5
z = -2
one = 1
three = 3
seven = 7
 
proc body(j: int) =
sum += abs(j)
if abs(prod) < 2^27 and j != 0: prod *= j
 
 
for j in countup(-three, 3^3, three): body(j)
for j in countup(-seven, seven, x): body(j)
for j in countup(555, 550 - y): body(j)
for j in countdown(22, -28, three): body(j)
for j in countup(1927, 1939): body(j)
for j in countdown(x, y, -z): body(j)
for j in countup(11^x, 11^x + one): body(j)
 
let s = ($sum).insertSep(',')
let p = ($prod).insertSep(',')
let m = max(s.len, p.len)
echo " sum = ", s.align(m)
echo "prod = ", p.align(m)</lang>
 
Note that for “countdown” we must change the sign of the step to insure that it is positive.
 
{{out}}
<pre> sum = 347,937
prod = -793,618,560</pre>
 
===Using an iterator===
If the sign of the step is not known (or may vary), it is no longer possible to use the previous method. One could use a while loop but it seems better to use an iterator.
 
<lang Nim>import math, strutils
 
var
prod = 1
sum = 0
 
let
x = +5
y = -5
z = -2
one = 1
three = 3
seven = 7
 
type Range = tuple[first, last, step: int]
 
func initRange(first, last, step = 1): Range = (first, last, step)
 
iterator loop(ranges: varargs[Range]): int =
for r in ranges:
if r.step > 0:
for i in countup(r.first, r.last, r.step):
yield i
elif r.step < 0:
for i in countdown(r.first, r.last, -r.step):
yield i
else:
raise newException(ValueError, "step cannot be zero")
 
for j in loop(initRange(-three, 3^3, three),
initRange(-seven, seven, x),
initRange(555, 550 - y),
initRange(22, -28, three),
initRange(1927, 1939),
initRange(x, y, -z),
initRange(11^x, 11^x + one)):
sum += abs(j)
if abs(prod) < 2^27 and j != 0: prod *= j
 
let s = ($sum).insertSep(',')
let p = ($prod).insertSep(',')
let m = max(s.len, p.len)
echo " sum = ", s.align(m)
echo "prod = ", p.align(m)</lang>
 
Note that we have defined a function “initRange” to create the ranges. This is needed to make the step optional. If we suppressed this requirement (i.e. we required the step to be always specified), we could get ride of “initRange” and write the loop this way:
 
<lang Nim>for j in loop((-three, 3^3, three),
(-seven, seven, x),
(555, 550 - y),
(22, -28, three),
(1927, 1939, 1),
(x, y, -z),
(11^x, 11^x + one)):
sum += abs(j)
if abs(prod) < 2^27 and j != 0: prod *= j</lang>
 
=={{header|Perl}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.