トップ «前の日記(2008-01-03) 最新 次の日記(2008-01-06)» 編集

Route 477



2008-01-04

[misc] そろそろ本気出す

  • 禁チャット
  • 禁LDR
  • 禁テトリスDS

最後のが一番危険

[biwascheme] let*の変換

let*はletのネストに変換できる。*1

(let* ((a 1) (b a)) (print a) (+ a b))
  ↓
(let ((a 1))
  (let ((b a))
    (print a) (+ a b)))

ということで、

  1. バインディングを最後から順番に取って、
  2. body = (let (bind) (body)) とする

という操作を繰り返せばよい。

…のだが、biwaschemeではbodyに複数の式を許しているので、最初だけ特別扱い(Pairで包まない)しなければならない。

    var ret = null;
    binds.to_array().reverse().each(function(bind){
      ret = new Pair(Sym("let"), 
               new Pair(new Pair(bind, nil),
                 ret == null ? body : new Pair(ret, nil)));
    })
    return ret;

というのでちょっと悩んだ。

再帰的に書けばこんな罠にははまらないっぽいんだが。

syntax-rulesで書いてみた例。

(define-syntax letstar
  (syntax-rules ()
    ((letstar ((var val)) body ...)
     (let ((var val)) body ...))
    ((letstar ((var val) (var2 val2) ...) body ...)
     (let ((var val))
       (let* ((var2 val2) ...) body ...)))))

(print (let ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) (list x y z))))

*1 letは最終的にlambdaに変換できるので、let*から直接lambdaに変換しても良いと思う

[scheme] syntax-rulesでdefine-structをつくる

去年書き忘れた記事。

MzSchemeにはdefine-structという構文(Common Lispのdefstructみたいなもの)があるらしくて、 Gaucheにもあったらいいなぁと思ったので作ってみた。

…とさらっと書いたけど非常に苦労しましたw

;; string-appendのシンボル版
(define (symbol-append . syms)
  (string->symbol 
    (apply string-append (map symbol->string syms))))

;; define-structという構文を定義
(define-syntax define-struct 
  (syntax-rules ()
    ((define-struct name props)
     (eval 
       `(begin
          (define-class 
            ,(symbol-append '< 'name '>) 
            () 
            ,(map 
               (lambda (sym)
                 `(,sym :init-keyword ,(make-keyword sym)
                        :accessor ,(symbol-append sym '-of- 'name)))
               'props))
          ,@(map
              (lambda (sym)
                `(define-method ,(symbol-append 'name '- sym '-set!)
                                ((obj ,(symbol-append '< 'name '>)) ,sym)
                   (slot-set! obj ',sym ,sym)))
              'props))
       (interaction-environment)))))

使用例。

(define-struct book (title jp-title))

(let1 bk (make <book> :title "SICP")
  (print (title-of-book bk))
  (book-jp-title-set! bk "(前略)構造と解釈")
  (print (jp-title-of-book bk))
  )

はっきり言ってsyntax-rules使う意味がない(パターンマッチ使ってない)。 define-macroで書き直してみようかと思ったけど気力が尽きたので省略。 あとevalをなんとかしたかったけど無理だった。

先輩はevalなし(syntax-rulesだけ)でできるって言うんだけどさ、無理じゃね? syntax-rulesじゃマクロ展開時にsymbol-appendを実行することができないんだし。

syntax-rulesでsymbol-appendが実装できれば別だけど…、いくらチューリング完全と言っても、 それはリスト操作についてであって、symbol->stringが実装できるわけではない。よね。