次の基本的なストップウォッチを Racket にまとめました (現在学習中ですが、最終的な目的はポモドーロ タイマーです)。
#lang racket
(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 '())
))
これは本来あるべきことを正確に行いますが、可変状態を回避するにはどうすればよいか疑問に思っていました。私が HTDP に従っている場合、これはミュータブルな状態が正当化されるような状況ですが、Wadler の「関数型プログラミングのためのモナド」を閲覧した後でも、set!
.
機能させるには、関数に引数を追加する必要があることを知っています。たとえばstart
、
(define (start [now (current-seconds)])
now)
同様のアプローチが と で機能する可能性がlap
ありstop
ます。
それでも、機能を復元するために追加の引数を追加した後、変数に値を格納するのではなく、引数も渡す必要があることはわかっていますが、この場合、これを活用して回避する方法もわかりませんset!
。
更新:以下の3つの回答はすべて非常に価値があるため(ありがとうございます!)、一意の正解としてマークしませんでした. 以下は、私の最初の質問に対する最小限の解決策です。これは、@Metaxal のループ提案と @Greg Hendershott の使用例を組み合わせたものです。
#lang racket
(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)])))