Hi, Sunanda,

[EMAIL PROTECTED] wrote:
> 
> To soup up the code, I wrote an elapse timer function. It's
> listed below with some samples of use. Feel free to use it.
> 
> The code is reasonably Rebollish (it uses a persistent local
> variable), but I'd appreciate feedback on better ways of
> acheiving the same, particularly:
> 
> 1. Can I avoid having to define the same refinement variable
> (unit-name) twice (unit-name-start and unit-name-end)?
> 
> 2. Any better suggestions for those awkward Pokes?
> 

I'd refactor the code to separate the behavior of an individual
watch (as an object with its own state) from the behavior of
the total collection of watches in existence at a given time
(given a just-for-fun name ;-).  Watches know how to start, stop,
and report their total times (in seconds), while the watchmaker
knows how to make a new watch, find a watch by the label placed
on it when he made it, and get reports from all of the watches.

The code below is fairly minimal, but I think it addresses most
of the capabilities you had in UNIT-TIMER (or could be extended
easily to include any I missed in a quick read-through).

It performs as follows...

The watchmaker can create new watches on demand, and a reference
to a watch *can* be kept to allow it to be used individually:

    >> a: watchmaker/new "frushlinger"
    >> a/start
    == 7:18:24.53
    >> b: watchmaker/new "schlocken"
    >> b/start
    == 7:18:38.37
    >> c: watchmaker/new "fleegle"
    >> c/start
    == 7:18:58.09

The watchmaker can provide a consolidated report (each watch can
return total elapsed time whether running or not):

    >> watchmaker/report-all
    == ["frushlinger" 46.03 "schlocken" 32.19 "fleegle" 12.47]
    >> watchmaker/report-all
    == ["frushlinger" 47.95 "schlocken" 34.11 "fleegle" 14.39]
    >> watchmaker/report-all
    == ["frushlinger" 49.43 "schlocken" 35.59 "fleegle" 15.87]

Watches can be individually operated:

    >> b/stop
    == 46.25
    >> watchmaker/report-all
    == ["frushlinger" 61.9 "schlocken" 46.25 "fleegle" 28.34]
    >> watchmaker/report-all
    == ["frushlinger" 63.16 "schlocken" 46.25 "fleegle" 29.6]

The watchmaker manages the entire collection, so it's not
necessary for watch references to be kept around when not
needed -- the watchmaker can find the watch (by label) for
later operation:

    >> a: b: c: none
    == none
    >> x: watchmaker/fetch "fleegle"
    >> x/stop
    == 85.96
    >> watchmaker/report-all
    == ["frushlinger" 125.78 "schlocken" 46.25 "fleegle" 85.96]
    >> y: watchmaker/fetch "frushlinger"
    >> y/stop
    == 140.99

The default REPORT-ALL just returns label/time pairs in the
order the watches were created.  However, the watchmaker can
provide the timings in other potentially-useful orders:

    >> watchmaker/report-all
    == ["frushlinger" 140.99 "schlocken" 46.25 "fleegle" 85.96]
    >> watchmaker/report-all/by-label
    == ["fleegle" 85.96 "frushlinger" 140.99 "schlocken" 46.25]
    >> watchmaker/report-all/by-time
    == ["schlocken" 46.25 "fleegle" 85.96 "frushlinger" 140.99]

Of course, the result could be processed by something like

    foreach [lab tot] watchmaker/report-all [ ... ]

for whatever purpose...

After all that blabbing, here's the code:

8<------------------------------------------------------------
watchmaker: make object! [

    collection: []

    watch: make object! [
        label: ""
        total: began: ended: 0
        reset: func [] [total: began: 0]
        start: func [] [began: now/time/precise]
        to-seconds: func [t [time!]] [
            t/hour * 60 + t/minute * 60 + t/second
        ]
        stop: func [/local ended] [
            ended: now/time/precise - began
            if time? began [
                began: 0
                total: total + to-seconds ended
            ]
        ]
        report: func [] [
            if time? began [stop start]
            reduce [label total]
        ]
    ]

    reset: func [] [collection: copy []]
    new: func [lbl [string!]] [
        last back insert tail collection make watch [label: lbl]
    ]
    fetch: func [lbl [string!]] [
        foreach this-watch collection [
            if lbl = this-watch/label [return this-watch]
        ]
        none
    ]
    report-all: func [/by-label /by-time /local rpt] [
        rpt: make block! length? collection
        foreach this-watch collection [
            insert tail rpt this-watch/report
        ]
        if by-label [sort/skip rpt 2]
        if by-time  [sort/skip/compare rpt 2 2]
        rpt
    ]
]
8<------------------------------------------------------------

HTH!

-jn-

-- 
; sub REBOL {}; sub head ($) {@_[0]}
REBOL []
# despam: func [e] [replace replace/all e ":" "." "#" "@"]
; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"}
print head reverse despam "moc:xedef#yleen:leoj" ;
-- 
To unsubscribe from this list, please send an email to
[EMAIL PROTECTED] with "unsubscribe" in the 
subject, without the quotes.

Reply via email to