((import (rnrs)) (define-syntax fn (lambda (x) (define (parse-args args acc) (define (finish opt) (if (null? acc) opt (append (reverse acc) opt))) (syntax-case args (&) (() (finish '())) ((& rest) (finish #'rest)) ((a . d) (parse-args #'d (cons #'a acc))))) (define (parse-body body acc) (syntax-case body () (() (reverse acc)) (((#(args ...) exprs ...) . rest) (with-syntax ((formals (parse-args #'(args ...) '()))) (parse-body #'rest (cons #'(formals exprs ...) acc)))))) (syntax-case x () ((_ #(args ...) exprs ...) #'(fn dummy #(args ...) exprs ...)) ((_ name #(args ...) exprs ...) (identifier? #'name) #'(fn name (#(args ...) exprs ...))) ((_ (#(args ...) exprs ...) ...) #'(fn dummy (#(args ...) exprs ...) ...)) ((_ name (#(args ...) exprs ...) ...) (identifier? #'name) (with-syntax ((((formals body ...) rest ...) (parse-body #'((#(args ...) exprs ...) ...) '()))) #'(letrec ((name (case-lambda (formals body ...) rest ...))) name)))))) (define-syntax def (syntax-rules () ((_ name expr) (define name expr)))) (define-syntax defn (syntax-rules () ((_ name #(args ...) body ...) (defn name (#(args ...) body ...))) ((_ name (#(args ...) body ...) ...) (define name (fn name (#(args ...) body ...) ...))))) (defn print #(& args) (for-each display args) (newline)) (defn t1 #(a b) (print a b)) (t1 1 2) (defn t2 (#(x) (print x)) (#(x y) (print x y))) (t2 1) (t2 1 2) (t2 2 1) (def mult (fn this (#() 1) (#(x) x) (#(x y) (* x y)) (#(x y & more) (apply this (this x y) more)))) (print (mult 1 2 3 4 5))Clojureでは[]がベクタになるけど、Schemeでは#()にしないといけないのでむしろうっとおしい感じがする。
動作確認はいつものR6RS処理系でやった。
なんでこんなものを書いたかと言えば、パターンマッチ部分でベクタにもマッチできるよなぁと思ったから。本当にただそれだけ。
No comments:
Post a Comment