ついにorとandを定義できた
私がRubyで書いているLisp方言、 [Nendo]の開発状況続き。
macroで構文をどんどん定義している。
ついに or と and が定義できた。ついでに let1 も。
先日定義したcondも使っている。すごい勢いで積み上がっていく感じが楽しいぞ。
(define let1
(macro (var expr body)
(list 'let (list (list var expr)) body)))
(define or
(macro lst
(define (or_iter lst)
(cond
((eq? 0 (length lst))
false)
((eq? 1 (length lst))
(let1 sym (gensym)
(list 'let1 sym (car lst)
(list 'if sym sym false))))
(else
(let1 sym (gensym)
(list 'let1 sym (car lst)
(list 'if sym sym (or_iter (cdr lst))))))))
(or_iter lst)))
(define and
(macro lst
(define (and_iter lst)
(cond
((eq? 0 (length lst))
true)
((eq? 1 (length lst))
(car lst))
(else
(list 'if (list 'not (list 'eq? 'false (car lst)))
(and_iter (cdr lst))
'false))))
(and_iter lst)))
これが実行結果
bash-3.2$ ./nendo
nendo> (or)
false
nendo> (or 1 2 3)
1
nendo> (or false false 3)
3
nendo> (and)
true
nendo> (and true)
true
nendo> (and 1 2 3)
3
nendo> (and false 2)
false
nendo> (and true 2)
2
nendo> (and 1 2 (print "3\n") (print "4\n") 5)
3
4
5
nendo> (and 1 2 false (print "3\n") (print "4\n") 5)
false
実は、gensym関数の実装はかなりサボっているのだ。 gensymで生成されるシンボルは若干ぶつかりにくいネーミングルールになっているだけ。いつかイタイ目に会うのかな。
nendo> (macroexpand '(or 1 2))
(let ((__gensym__10 1)) (if __gensym__10 __gensym__10 (let ((__gensym__11 2)) (if __gensym__11 __gensym__11 false))))
このへんがToy言語っぽい。何とかしたい…