[REBOL] Re: for bug?
From: joel:neely:fedex at: 18-Jun-2002 22:49
Hi, Gabriele,
Gabriele Santilli wrote:
> Interesting idea... something like:
>
> for: func [
...
> ][
...
> ]
>
> Do you see any problems with it?
>
There's good news and bad news:
1) A QAD test indicates a big performance win. After renaming
your posted version to NEWFOR, I ran the following (wrapped
for the email):
t0: now/time/precise
for i 1 10000000 1 []
t1: now/time/precise - t0
and got
== 0:01:14.557616
than ran:
t0: now/time/precise
newfor i 1 10000000 1 []
t1: now/time/precise - t0
and got
== 0:00:59.648256
which shows about a 20% reduction in run time.
2) This does, indeed, solve Romano's problem with using FOR to
iterate through char! values, as shown by:
n: 0
newfor i #"^(00)" #"^(ff)" 51 [
n: n + 1
print [n tab to-integer i]
if n > 10 [break]
]
which gives:
1 0
2 51
3 102
4 153
5 204
6 255
== none
versus:
n: 0
for i #"^(00)" #"^(ff)" 51 [
n: n + 1
print [n tab to-integer i]
if n > 10 [break]
]
which exhibits Romano's Syndrome:
1 0
2 51
3 102
4 153
5 204
6 255
7 50
8 101
9 152
10 203
11 254
== none
(Of course the business with N was to compensate for my slow
reaction time on the "Escape" key! ;-)
3) I believe that (with a bit more work) NEWFOR could be extended
to handle tuple! ranges as well. Being able to iterate thru
a collection of IP addresses or skip through color space seems
to be useful.
On the other hand...
1) Integer ranges wider than the maximum integral value break
the computation of iteration count; with the existing FOR:
for i -2147483647 1147483647 1000000000 [print i]
we get behavior as expected:
-2147483647
-1147483647
-147483647
852516353
while with the new version:
newfor i -2147483647 1147483647 1000000000 [print i]
we get a new breakage mode:
** Math Error: Math or number overflow
** Where: newfor
** Near: times: 1 + to-integer divide
I had planned on adding a later note that the iteration
count computation would need to be performed in decimal!
(with suitable protection against round-off error
contaminating the iteration count), due to just this issue,
but I had a class that kept me to busy to remember that
follow-up.
2) There's a bit more work needed in loop unrolling to prevent
edge-of-domain failure:
>> newfor i 2147483637 2147483647 2 [print i]
2147483637
2147483639
2147483641
2147483643
2147483645
2147483647
** Math Error: Math or number overflow
** Where: newfor
** Near: start: start + bump
something along the lines of replacing
times: 1 + to-integer divide subtract end start bump
loop times [
set/any 'result do-body start
start: start + bump
]
with
if 0 < times: i + to-integer (end - start) / bump [
set/any 'result do-body start
loop times - 1 [
start: start + bump
set/any 'result do-body start
]
]
seemed to do the trick:
>> newfor i 2147483637 2147483647 2 [print i]
2147483637
2147483639
2147483641
2147483643
2147483645
2147483647
3) The "bit more work" to address tuple! values would have to
deal with calculating the "width" of a range of tuple values,
and the peculiar behavior of tuple arithmetic (perhaps to
correct it, at least for the purpose of NEWFOR!)
>> baseIP: 255.0.0.0
== 255.0.0.0
>> loop 20 [print baseIP: baseIP + 0.10.20.30]
255.10.20.30
255.20.40.60
255.30.60.90
255.40.80.120
255.50.100.150
255.60.120.180
255.70.140.210
255.80.160.240
255.90.180.255
255.100.200.255
255.110.220.255
255.120.240.255
255.130.255.255
255.140.255.255
255.150.255.255
255.160.255.255
255.170.255.255
255.180.255.255
255.190.255.255
255.200.255.255
However, I think that's a very manageable task.
Thanks for the amazingly quick post!
-jn-
--
; Joel Neely joeldotneelyatfedexdotcom
REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip
do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] {
| e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]