Mailing List Archive: 49091 messages

## [REBOL] Re: Benchmarking alternatives

### From: joel:neely:fedex at: 6-Nov-2001 14:54

```
Ryan Cole wrote:
> ...  Do you know of a way I can take advantage of this gain
> inside a block?
>
> >> blk: []
> == []
> >> append/only blk to-paren [1 + 1]
> == [(1 + 1)]
> >> b/1
> == (1 + 1)
> >> append/only blk does [1 + 1]
> == [(1 + 1) func [][1 + 1]]
> >> b/2
> == 2
> >>
>

(I assume you meant to use BLK instead of B, which interestingly
seems to be synonymous???  Oh, well, back to your question...)

I don't know any way to get the paren evaluated without some
Obviously, given

>> blk: []
== []
>> append/only blk to-paren [1 + 1]
== [(1 + 1)]
>> append/only blk does [2 + 2]
== [(1 + 1) func [][2 + 2]]

one could use any of the following

>> reduce blk
== [2 4]

or

>> do blk/1
== 2

or, oddly enough,

>> x: blk/1
== (1 + 1)
>> x
== 2

Maybe someone else has a trick or two that can help here...

Meanwhile, my target was the kind of thing where one constructs or
selects a block to be DOne later, or uses such a block to build
a DOES function.  A dinky example might help illustrate...

Consider the task of summing up the reciprocals of some positive
integers *or* summing the reciprocals of their squares (depending
on the presence of a switch).  The brute-force solution

tally-inside: func [limit [integer!] /squares /local t] [
n: t: 0
while [n < limit] [
n: n + 1
either squares [
t: 1.0 / n / n + t
][
t: 1.0 / n + t
]
]
t
]

keeps making the same decision over and over and over and ...

The first (commonly-seen) optimization is to move the decision
out of the loop by constructing/selecting a block to be repeated,
doing this prior to the beginning of the loop.

tally-outside: func [limit [integer!] /squares /local t incr] [
incr: either squares [[
t: 1.0 / n / n + t
]][[
t: 1.0 / n + t
]]
n: t: 0
while [n < limit] [n: n + 1  do incr]
t
]

This give a time savings of a few percent.  OTOH, constructing a
paren to hold (and evaluate) the appropriate expression, as in:

tally-paren: func [limit [integer!] /squares /local t incr] [
incr: to-paren either squares [[
t: 1.0 / n / n + t
]][[
t: 1.0 / n + t
]]
n: t: 0
while [n < limit] [n: n + 1  incr]
t
]

saves more.  Interestingly enough, using the paren for only a
*part* of the expression, as in:

tally-recip: func [limit [integer!] /squares /local t term] [
term: to-paren either squares [[ 1.0 / n / n ]][[ 1.0 / n ]]
n: t: 0
while [n < limit] [n: n + 1  t: term + t]
t
]

provides yet another competitive option.

Of course, I'm well aware that there are other ways to perform
this *particular* computation, but the point was to focus on how
to pull a decision out of a loop.  I chose a simple example, not
because I couldn't think of other ways to do this piece of
arithmetic, but to illustrate the refactoring without bogging
down in a complicated example.

-jn-

--
It's amazing how polific Ibid was.
-- Amy Johnson
joel'dot'neely'at'FIX'PUNCTUATION'fedex'dot'com
```