and-let* の嫌なところを除いた let*-and をマクロで実装をしてみた。syntax-case でなく syntax-rules での簡易実装だからユーザーが間違って使った場合のエラーを排除仕切れないけど差し当たりは良しとする。syntax-case が良く分からないので。
仕様
-
let*-and :=
(let*-and (束縛節…)本体式…) -
束縛節 :=
(変数名評価値が束縛される式) -
束縛節 :=
(変数名評価値が束縛される式(where条件式))
let* と同じように、束縛節が左から右に順に処理される。
(wher 条件式) がある場合は、次の束縛節が処理される前に条件式が評価されて、それが #f なら次の束縛節の処理は実行されずに let*-and 全体の評価が終わる。その値は #f になる。
それ以外の場合、最後に評価された(=最も右にある) 本体式 または 条件式 または 評価値が束縛される式 の値が let*-and 全体の評価値になる。
束縛節… も 本体式… もどちらも空にすることができて、両方が空の (let*-and ()) の評価値は #t。
コード
(define-syntax let*-and
(syntax-rules (where)
((let*-and ())
; then
#t)
((let*-and (clause clauses ...))
; then
(let*-and
"let*-and clauses:" (clause clauses ...)
"let* clauses:" ()))
((let*-and (clauses ...) body bodies ...)
; then
(let*-and
"let*-and clauses:" (clauses ... ["begin" body bodies ...])
"let* clauses:" ()))
;; implements ...
((let*-and
"let*-and clauses:" (["begin" body bodies ...])
"let* clauses:" (let*_clauses ...))
; then
(let* (let*_clauses ...) body bodies ...))
((let*-and
"let*-and clauses:" ([var expr (where pred)])
"let* clauses:" (let*_clauses ...))
; then
(let* (let*_clauses ... (var expr)) pred))
((let*-and
"let*-and clauses:" ([var expr])
"let* clauses:" (let*_clauses ...))
; then
(let* (let*_clauses ... [var expr]) var))
((let*-and
"let*-and clauses:" ([var expr (where pred)] let*-and_clauses ...)
"let* clauses:" (let*_clauses ...))
; then
(let* (let*_clauses ... [var expr])
(and pred
(let*-and
"let*-and clauses:" (let*-and_clauses ...)
"let* clauses:" ()))))
((let*-and
"let*-and clauses:" ([var expr] let*-and_clauses ...)
"let* clauses:" (let*_clauses ...))
; then
(let*-and
"let*-and clauses:" (let*-and_clauses ...)
"let* clauses:" (let*_clauses ... [var expr])))))