Gaucheのlambda shorter-namesをR6RSで実装する

lambdaのshorter-name( http://blog.practical-scheme.net/gauche/20100428-shorter-names )は便利な機能なので、nmoshにはコッソリ入れておくことにする。

^

^は以前reader macroで実装していたのを、単にsyntax-rulesに変更した。

(define-syntax ^
  (syntax-rules ()
    ((_ args ...)
     (lambda args ...))))

以前( http://d.hatena.ne.jp/mjt/20091207/p1#c1260348087 )のコードそのまま。

^x

会社で使っているnmoshでは、この機能をexpanderを変更する形で実装している。というのも、syntax-rulesでは新たなシンボルの導入が事実上できないので、このような"本来存在しない"シンボルを導入するのはsyntax-rulesの範囲では行えない。
R6RSはsyntax-caseが有るので、原理的にはsyntax-caseで対応することができる。
まず、^aを作ってみる。

(define-syntax ^a
  (lambda (x)
    (syntax-case x ()
      ((k args ...)
       (with-syntax ((name (datum->syntax #'k 'a)))
         #`(lambda (name) args ...))))))

これはR6RS 12.6のサンプルから採ってきた。
あとは、これを26x2個コピペしても良いが、我々は文明人なのでマクロを使う。

(define-syntax define-onechar-lambdas
  (lisp-transformer
    (lambda (f)
      (define (entry name)
        (let ((namestr (symbol->string name)))
          `(define-syntax ,(string->symbol (string-append "^" namestr))
             (lambda (x)
               (syntax-case x ()
                 ((k args ...)
                  (with-syntax ((larg (datum->syntax #'k (quote ,name))))
                    #'(lambda (larg) args ...))))))))
      (let ((l (cdr f)))
        (cons 'begin (map entry l))))))
(define-onechar-lambdas
  a b c d e f g h i j k l m n o p q r s t u v w x y z
  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)

lisp-transformerはLisp風マクロのためのtransformerで、この定義もR6RS 12.6に有る。
いわゆるControl-charと見間違う罠が有るが、mapやfor-eachのような関数を取る関数には非常に便利。
syntax-caseで実装すると、1文字分に一つlambdaが出来てもったいないという問題以外に、^hogehogeのような複数文字に対応するのが面倒という問題が有る。会社のnmoshにはシンボルの再解釈機能をパーサに仕込んでいて、それを使って ^ 文字をリパースすることで一種のリードマクロを実現している(ちなみに、この機能を使ってキーワード構文も実装している)。
複数文字はサポートしないので[ ]による記述を推奨したい。

prism:~ oku$ nmosh
nmosh top program
nmosh> (map (^[target] (+ 1 target)) '(1 2 3))
(2 3 4)

今度はリテラル正規表現と見間違えるかもしれないが。。