let*と名前付きletをマクロで

30分プログラム、その681。let*と名前付きletをマクロで書いてみました。
輪講のためにSICPの演習問題を解いてたら、「let*と名前付きletをコード変換で実現しろ」というのがでてきました。
そのとき、パターンマッチが使えなくてフラストレーションが溜りまくったので、マクロで再実装しました。
でも、マクロだと引数の部分で(簡易的な)パターンマッチが使えるので、util.matchはあんまり使いませんでした。

使い方

;; let*の例
(my-let* ((x 3)
	  (y (+ x 2)))
	 (+ x y))

;; 名前付きlet
(define (fib n)
  (my-let fib-iter ((a 1)
		    (b 0)
		    (count n))
	  (if (= count 0)
	      b
	      (fib-iter (+ a b) a (- count 1)))))

ソースコード

#! /opt/local/bin/gosh
;; -*- mode:scheme; coding:utf-8 -*-
;;
;; let-star.scm -
;;
;; Copyright(C) 2009 by mzp
;; Author: MIZUNO Hiroki / mzpppp at gmail dot com
;; http://howdyworld.org
;;
;; Timestamp: 2009/10/21 21:44:01
;;
;; This program is free software; you can redistribute it and/or
;; modify it under MIT Lincence.
;;

(use util.match)

(define-macro (my-let . args)
  (match args
	 [(name bindings body)
	  `(begin
	     (define (,name ,@(map car bindings)) ,body)
	     (,name ,@(map cadr bindings)))]
	 [(bindings body)
	  `((lambda ,(map car bindings) ,body)
	    ,@(map cadr bindings))]))

(define-macro (my-let* bindings body)
  (fold-right (lambda (binding rest) `(let (,binding) ,rest))
	      body
	      bindings))

(define (fib n)
  (my-let fib-iter ((a 1)
		    (b 0)
		    (count n))
	  (if (= count 0)
	      b
	      (fib-iter (+ a b) a (- count 1)))))

(my-let* ((x 3)
	  (y (+ x 2)))
	 (+ x y))