cutの実装

とりあえず明日の仕事というか宿題が終わったので、schemeに戻れる。
まずどっちからやろうかな、と考えて、より大変そうなcutからやってみる。早速 srfi-26を覗いてみる。
と、こんな感じの入り口マクロに

(define-syntax cut
  (syntax-rules ()
    ((cut . slots-or-exprs)
     (srfi-26-internal-cut () () . slots-or-exprs))))  

こんな感じの本体マクロのセット(本質的なところだけを抜き出しています)。

(define-syntax srfi-26-internal-cut
  (syntax-rules (<>)

    ;; construct fixed- or variable-arity procedure:
    ;;   (begin proc) throws an error if proc is not an <expression>
    ((srfi-26-internal-cut (slot-name ...) (proc arg ...))
     (lambda (slot-name ...) ((begin proc) arg ...)));;(0)

    ;; process one slot-or-expr
    ((srfi-26-internal-cut (slot-name ...)   (position ...)      <>  . se) 
     (srfi-26-internal-cut (slot-name ... x) (position ... x)        . se));;(1)
    ((srfi-26-internal-cut (slot-name ...)   (position ...)      nse . se)
     (srfi-26-internal-cut (slot-name ...)   (position ... nse)      . se))));;(2)

やっている事は単純で、(1),(2)のルールでcut以降の式を順に走査していき、<>が出てきたら(1)でlambdaの引数に書き換え、そう出なければそのまま、という置き換えを繰り返し、式が空になったら(0)のルールでごそっと lambdaでくるむ。というやりかた。
ちょうど、srfi-26-internal-cutの1つめのリストが後からlambdaの引数リストになる部分で、2つめのリストが式本体(の<>をlambdaの引数に置き換えた物)となる。
で、ネストしたリストのcutが上手くいかないのは、(1),(2)がdeepに見れないから、で、そう考えると以下の動作は非常にナットク。

gosh> ((cut not (equal? <> 0)) 0)
*** ERROR: Compile Error: wrong number of arguments: #f requires 0, but got 1
"(stdin)":357:((cut not (equal? <> 0)) 0)

Stack Trace:
_______________________________________
gosh> ((cut not (equal? <> 0)))
*** ERROR: unbound variable: <>
Stack Trace:
_______________________________________
  0  (equal? <> 0)
        At line 358 of "(stdin)"

上記の場合 equal?のリストの中まで走査しないので<>は読まれず、 (lambda () (not (equal? <> 0))) になってしまう。だから引数を与えれば怒られるし、引数を与えなければ <>が不正だと怒られる。なるほど。
こんな使い方しなければ良い(実際ネストした奴にcut入れるのは何となく違和感がある)のだけれど、折角なのでなんとかしてみようとしてハマる。

(define-syntax my-inner-cut
	(syntax-rules (<>)
	  ((my-inner-cut (slots ...) (exprs ...))
	   (lambda (slots ...) (exprs ...)))

          ;; nest解析部
	  ((my-inner-cut (slots ...) (exprs ...) (h . t) . rest)
	   (my-inner-cut (slots ...) (exprs ...) (my-inner-nest () () (h . t)) . rest))

	  ((my-inner-cut (slots ...) (exprs ...) 'inner params trans . rest)
	   (my-inner-cut (slots ... params) (exprs ... trans) . rest))

          ;;走査部
	  ((my-inner-cut (slots ...) (exprs ...) <> . rest)
	   (my-inner-cut (slots ... x) (exprs ... x) . rest))
	  ((my-inner-cut (slots ...) (exprs ...) ns . rest)
	   (my-inner-cut (slots ...) (exprs ... ns) . rest))))

とかして my-inner-nestで、云々とか・・・・うわーワケワカランくなってきた。難しい過ぎる。というかこれは思考の迷宮状態なのでもうダメ。一時あきらめて撤退。改めて挑戦(する意味は無いのかもしれない)。