[REBOL] Re: Translate this code into real Rebol?
From: jeff:rebol at: 23-Jan-2002 17:00
Another entry for the number pretty printer:
pretty-number: func [
in-amt [money! integer! decimal!]
/local i-part f-part h-part out e neg get-high
thousands-sep decimal-sep currency p-amt zpad
][
decimal-sep: #. thousands-sep: #, currency: #£
set [i-part neg f-part get-high zpad] reduce [
abs to-integer any [
all [money? in-amt out: copy currency in-amt: in-amt/2]
all [out: copy currency: # in-amt]
]
pick ["-" ""] negative? in-amt
do pick [[join decimal-sep f-part] #]
found? f-part: find/reverse/tail tail form in-amt #.
func [x m /local p s][
reduce either x > p: 10 ** m [[s: to-integer x / p x - (s * p)]][[# x]]
]
func [e x][either e [x][skip tail append copy #000 x -3]]
]
for i 99 3 -3 [
set [h-part i-part] get-high i-part i
if any [not e: currency = out number? h-part][
repend out [zpad e h-part thousands-sep]
]
]
rejoin [neg out zpad e i-part f-part]
]
commentary: {
This has various REBOL idioms mixed in with my own.
The way I did the function is a common approach I find I do in
programming: breakdown, process, synthesize. In REBOL that
amounts to first setting various locals, then doing some
processing loop, ending with some kind of REDUCE or JOIN.
Another REBOL idiom used is to "piggy-back" work in certain
convenient places, for example, in the process of setting
'i-part I conditionally extract the number portion of in-amt
if it's a money! in turn making sure that my output string is
initialized with the currency or not depending on if money?.
Similarly, I "piggy-back" all the word setting together,
(except for the three user-vars which I left at the top).
I tried to avoid the RT favorite bug-bear, which is to turn
all problems into pure string processing. Working with the
item-in-question's natural datatype (number), with the notable
exception of handling the fractional part.
One of my idioms is I often (ab)use issue! datatype. That's
because no one seems to use it and I want to be original. (-:
To ensure we get a string result, I just make sure NEG is a
string.
Another handy REBOL idiom is to have a function which returns
a block. The block contains your "answer" as well as the next
increment. You can see this with
set [h-part i-part] get-high i-part i
'I-part gets moved along by each call to GET-HIGH. For
example, look at LOAD/next and DO/next.
Lets see.. I also removed the brackets refinement because I
felt it didn't go with the function, but should go somewhere
else.
Now, Joel may benchmark these functions and demonstrate that
my code is not the optimal solution. (-: This is likely
because of the inner functions among other things. Inner
functions are used when you want to share context, but in the
case above, I defined them inside the function because they go
with its "thinking". They'll likely be a performance hit,
though (among other things).
But efficiency wasn't a condition to play, so the optimization
can be left as an exercise for performance critical uses.
-jeff
}