; Dibvig-3.5.2-1
(define calc1
(lambda (exp)
(define-syntax complain
(syntax-rules ()
((_ e1 e2 e3) (e1 (list e2 e3)))))
(call/cc
(lambda (ek)
(define apply-op
(lambda (ek op args)
(op (do-calc ek (car args)) (do-calc ek (cadr args)))))
(define do-calc
(lambda (ek exp)
(cond
((number? exp) exp)
((and (list? exp) (= (length exp) 3))
(let ((op (car exp)) (args (cdr exp)))
(case op
((add) (apply-op ek + args))
((sub) (apply-op ek - args))
((mul) (apply-op ek * args))
((div) (apply-op ek / args))
(else (complain ek "invalid operator" op)))))
(else (complain ek "invalid expression" exp)))))
(do-calc ek exp)))))
gosh> (calc1 '(div 2 3))
=> 0.6666666666666666
gosh> (calc1 '(div (div (div 3 2)) 2))
=> ("invalid expression" (div (div 3 2)))
エラー処理もうまくいっている。で、ここからcall/ccを削除したいんだけど、単純に次のようにしてはダメらしい。
; Dibvig-3.5.2-2
(define calc2
(lambda (exp)
(define-syntax complain
(syntax-rules ()
((_ e1 e2) (list e1 e2))))
(let ()
(define apply-op
(lambda (op args)
(op (do-calc (car args)) (do-calc (cadr args)))))
(define do-calc
(lambda (exp)
(cond
((number? exp) exp)
((and (list? exp) (= (length exp) 3))
(let ((op (car exp)) (args (cdr exp)))
(case op
((add) (apply-op + args))
((sub) (apply-op - args))
((mul) (apply-op * args))
((div) (apply-op / args))
(else (complain "invalid operator" op)))))
(else (complain "invalid expression" exp)))))
(do-calc exp))))
gosh> (calc2 '(div 2 3))
=> 0.6666666666666666
gosh> (calc2 '(div (div (div 3 2)) 2))
=> *** ERROR: operation / is not defined between ("invalid expression" (div (div 3 2))) and 2
Stack Trace:
_______________________________________
エラー処理がうまくない。一回だけエラー処理をしているけど、そこで抜けられていない。apply-opの再帰を継続引き渡しで書き直せばいいのかな?
0 件のコメント:
コメントを投稿