Simple Scheme で電卓をつくってみる(8)
さらに心理的に落ち着くために、これからしようとしている計算が足し算なのか引き算なのか掛け算なのか割り算なのかを表示するようにしましょう。
そのためには、これからしようとしている計算を表す記号を電卓の表示機構に知らせる必要があります。
まず演算記号のリストと関数のリストを作りましょう。このとき、対応する記号と関数が同じ添字の位置に来るようにします。*1
(define op-no 0) (define op-labels (list "" "+" "-")) ; ... (define op-alist (list (list "" get2nd) (list "+" add) (list "-" sub))) (define ops (map (lambda (l) (cadr (assoc l op-alist))) op-labels))
そして、make-op
に直接add
等を渡すのをやめて、番号(op-no
)を渡すことにします。
(define (make-op i) (lambda () (begin (and (symbol=? mode inputting) (begin (set! result ((list-ref ops op-no) result input)) ; add等へは添字でアクセスする (set! window result))) (set! op-no i) (set! mode waiting))))
この番号は主にop-labels
やops
にアクセスするための添字として、また演算記号の表示位置を決めるための値としても使用します。
(define overlay-window (let* ((wdx (* width (/ 3/4 (+ max-ndigits 1/2)))) (iwdx (round wdx)) (wy (* width 9/64)) (sy (* width 5/64)) (sconv-x (lambda (x) (round (* width (- 9/10 (* 1/20 x))))))) (lambda (scn) (let* ((lis (map number->string (append (num-i window) (num-f window)))) (wconv-x (lambda (x) (round (+ (* width 1/8) (* wdx (+ x (- max-ndigits (length lis)) 1)))))) (scn (place-image (text (list-ref op-labels op-no) 60 "#888") ; ここと (sconv-x op-no) sy scn))) ; ここ (foldl (lambda (x scn) (place-image (text (car x) iwdx "black") (cadr x) wy scn)) (place-image (text "." iwdx "black") (wconv-x (- (length (num-i window)) 0.5)) wy (place-image (text (num-sign window) iwdx "black") (wconv-x -0.8) wy scn)) (build-list (length lis) (lambda (i) (list (list-ref lis i) (wconv-x i)))))))))
実際に動かしてみたのがこちらです*2。
— brv00 (@brv00) 2019年11月17日
他にもいろいろ変えたので列挙しておきますね。
続きます。