gaucheで可変引数で計算量の少ない=を作る

gaucheで可変引数で計算量の少ない=を作る

(print (call/cc (lambda (cc) (fold (lambda (x y) (if (eq? x y) x (cc #f))) (begin (write 1) 7) (list (begin (write 2) 7) (begin (write 3) 7))))))
;=>1237
(print (call/cc (lambda (cc) (fold (lambda (x y) (if (eq? x y) x (cc #f))) (begin (write 1) 0) (list (begin (write 2) 7) (begin (write 3) 7))))))
;=>123#f

うーん。これだと全部の引数を評価してしまうなぁ。

andの定義をR5RSで見てみると

(define-syntax and2
  (syntax-rules ()
    ((and2) #t)
    ((and2 test) test)
    ((and2 test1 test2 ...)
     (if test1 (and2 test2 ...) #f))))

(and2 (begin (write 1) #t) (begin (write 2) #t) (begin (write 3) #f)(begin (write 4) #t))
;=>123#f

すごいこれ。引数の数でパターンマッチさせるのか。

てことで定義してみた。

(define-syntax =2
  (syntax-rules ()
    ((=2) #f)
    ((=2 t) t)
    ((=2 t1 t2)
     (let ((x t1)(y t2)) (if (eq? x y) x #f)))
    ((=2 t1 t2 t3 ...)
     (let ((x (=2 t1 t2))) (if x (=2 x t3 ...) #f)))))

(print "\t," (=2 (begin (write 1) 7)))
(print "\t," (=2 (begin (write 1) 7) (begin (write 2) 7)))
(print "\t," (=2 (begin (write 1) 7) (begin (write 2) 8)))
(print "\t," (=2 (begin (write 1) 7) (begin (write 2) 7) (begin (write 3) 7)(begin (write 4) 7)))
(print "\t," (=2 (begin (write 1) 7) (begin (write 2) 8) (begin (write 3) 7)(begin (write 4) 7)))
;=>1	,7
;=>12	,7
;=>12	,#f
;=>1234	,7
;=>12	,#f

できた。