## [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 additional overhead, which (of course) defeats the whole idea. 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