いろいろ間違ってた。
先日のschemeのプログラムは色々間違ってた。
x消去で、xを含まない合成手続きXを K X と処理すべきが、
S (K Y) (K Z) になってた。コンビネータとしては冗長だけど、間違ってはいない。といいわけしておく。
ついでにutil.matchを使って書き直してみた。(中途半端ではあるが)
かなりすっきり。
(toSK '(x y) '(y x)) => (S (K (S I)) K)
(use util.match) (define combinator-split (match-lambda [(? symbol? a) (values a '())] [(a) (values a '())] [(a b) (values a b)] [(a b c) (values (list a b) c)] [(a b c . rest) (receive (new-a new-b) (combinator-split (cons b (cons c rest))) (values (cons a new-a) new-b))])) (define (find_var v l) (if (eq? v l) #t (find (lambda (m) (cond ((not (pair? m)) (eq? m v)) ((null? m) #f) (else (find_var v m)))) l))) (define (only? v X) (or (eq? v X) (and (pair? X) (null? (cdr X)) (symbol? (car X)) (eq? v (car X))))) (define (var_delete v X) (receive (Y Z) (combinator-split X) (cond ((null? Z) (cond ((only? v Y) 'I) (else `(K ,Y)))) ((and (only? v Z) (not (find_var v Y))) Y) ((and (not (find_var v Y)) (not (find_var v Z))) `(K ,X)) (else `(S ,(var_delete v Y) ,(var_delete v Z)))))) (define (toSK vars body) (define (toSK-iter r-vs l) (if (null? r-vs) l (toSK-iter (cdr r-vs) (var_delete (car r-vs) l)))) (toSK-iter (reverse vars) body))
まあでも
(toSK '(x y) '((y x)))
みたいな入力だと相変わらずバグるんだが。
不要な括弧をリストから除くユーティリティがあればいいのか?
((x y z)) ;;-> (x y z) ((x) (y) (z)) ;;-> (x y z) (x ((y y))) ;;-> (x (y y)) ((x y) z) ;;-> (x y z) ;; これはやらなくてもいい
みたいな。
どうすればいいのかは思い付かない。