I put together the next rudimentary stopwatch in Racket (just studying now, the final goal is a pomomoro timer).
(define start-time 0)
(define end-times '())
(define (start);; stores start-time
(set! start-time (current-seconds)))
(define (lap);; stores "laps" in list
(set! end-times (cons (current-seconds) end-times)))
(define (stop);; stores final time, displays lap-times in h, m, s and resets end-times
(begin
(set! end-times (cons (current-seconds) end-times))
(display
(reverse
(map (lambda (an-end)
(let ((the-date (seconds->date(- an-end start-time))))
(list
(sub1(date-hour the-date))
;; sub1 is needed because (date-hour(seconds->date 0) = 1
(date-minute the-date)
(date-second the-date)))) end-times)))
(set! end-times '())
))
While this does exactly what I need, I was wondering how I can avoid a volatile state. If I follow HTDP, it is such a situation where the mutable state is justified, but after watching Wadler's " Monads for Functional Programming ", I am still curious how I could do without set!.
I know that for its functionality I have to add arguments to my functions. For example, startwill
(define (start [now (current-seconds)])
now)
and a similar approach can work with lapand stop.
, , , , , , set!.
: (!), . . - @Metaxal @Greg Hendershott.
(define (run)
(displayln "Enter 'lap' or 'quit':")
(let loop ([t0 (current-seconds)] [times '()])
(match (read-line)
["quit" (reverse
(map (lambda (x)
(let ((the-date (seconds->date x)))
(list
(sub1(date-hour the-date))
(date-minute the-date)
(date-second the-date)))) times))]
["lap" (loop t0 (cons (- (current-seconds) t0) times))]
[_ (loop t0 times)])))