2010/05/09

Common Lisp の labels を Scheme の衛生的マクロで書いてみる

こんな感じでどうでしょうか。

;; Common Lisp : labels
(define-syntax labels
(syntax-rules ()
((_ ((name (var)
proc-body))
body)
(letrec
((name (lambda (var)
proc-body)))
body))))
;; test
(labels ((fact (n)
(if (zero? n)
1
(* n (fact (- n 1))))))
(fact 5))
; -> 120
(define-syntax labels
(syntax-rules ()
((_ ((name (var ...)
proc-body ...))
body ...)
(letrec
((name (lambda (var ...)
proc-body ...)))
body ...))))
(labels ((fact (n)
(if (zero? n)
1
(* n (fact (- n 1))))))
(fact 5))
; -> 120
;; test
(labels ((fact (n acc)
(if (zero? n)
acc
(fact (- n 1)(* n acc)))))
(fact 5 1))
; -> 120
;; test
(labels ((fact (n acc)
(format #t "n = ~a, acc = ~a\n" n acc)
(if (zero? n)
acc
(fact (- n 1)(* n acc)))))
(fact 5 1))
;; test
(for-each (lambda (e)
(print e))
(list (odd? 11)
(odd? 22)
(even? 11)
(even? 22)))
;; #t
;; #f
;; #f
;; #t
;; #<undef>
(labels ((odd? (n)
(if (zero? n)
#f
(even? (- n 1))))
(even? (n)
(if (zero? n)
#t
(odd? (- n 1)))))
(for-each (lambda (e)
(print e))
(list (odd? 11)
(odd? 22)
(even? 11)
(even? 22))))
; -> error
(define-syntax labels
(syntax-rules ()
((_ ((name (var ...)
proc-body ...) ...)
body ...)
(letrec
((name (lambda (var ...)
proc-body ...)) ...)
body ...))))
;; test
(labels ((my-odd? (n)
(if (zero? n)
#f
(my-even? (- n 1))))
(my-even? (n)
(if (zero? n)
#t
(my-odd? (- n 1)))))
(display (list (my-odd? 11)
(my-odd? 22)
(my-even? 11)
(my-even? 22))))
; -> (#t #f #f #t)#<undef>
view raw labels.scm hosted with ❤ by GitHub


うーん、どうだろ。

プログラミングGauche

0 件のコメント:

コメントを投稿