I have noticed that the if statement can be a bit tricky for the new programmer. Not because they don’t understand how it works, but because they wish to put more than one statement for the positive or negative clause, especially when debugging. I am reluctant to direct a new student to the more complicated looking cond, and likewise begin can make their programs too intimidating.
My solution was to create a new if, the lif, which separates the positive clause from the negative with an else, here is an example of what it should look like in actions:
(lif (null? x) (display x) #f else (display (cdr x)) #t)
Initially I thought this would be an easy task, but scheme’s pattern matchers in their macros will only accept one … at a given level of nesting, so I was forced to write an intermediate macro called lif-i
(define-syntax lif-i
(lambda (x)
(syntax-case x (else)
(
(lif-i condition else (neg ...))
(syntax (unless condition (begin neg ...)))
)
(
(lif-i condition pos ... else (neg ...))
(syntax (if condition (begin pos ...) (begin neg ...)))
)
(
(lif-i condition pos ...)
(syntax (if condition (begin pos ...)))
)
)))
If we were to use lif-i directly it would look like:
(lif-i (null? x) (display x) #f else ((display (cdr x)) #t))
lif could then be implemented as a macro that collects the statements after an else into a list, and then uses lif-i to do the rest of the work.
(define-syntax lif
(lambda (x)
(let ((lst (cdr (syntax-object->datum x))))
(letrec ((elser (lambda (l)
(cond ((null? l) '())
((eq? (car l) 'else) (list 'else (cdr l)))
(else (cons (car l) (elser (cdr l))))))))
(datum->syntax-object (syntax k) (cons 'lif-i (elser lst)))))))