Hello
I've noticed some time ago that (begin) is the best thing a macro can return if it doesn't want to insert any code. Like: (define-macro (STRIP . x) '(begin)) or (define-macro (toggle-foo-at-compile-time) (set! foo (not foo)) '(begin))
It's better than returning #f or #!void since (begin) even works when being put before internal definitions or declarations at the start of a function, like:
(define (bar x) (toggle-foo-at-compile-time) (define a 5) ...)
Encouraged by this, I hoped that it would also work in tail position, e.g. just disappear and not disturb delivery of the return value. Like:
(define (baz x) (toggle-foo-at-compile-time) (+ baz 5) (toggle-foo-at-compile-time))
But this is giving a compilation error, "Ill-formed special form: begin".
Simpler test cases:
; this is the only case which doesn't give a compile-/expansion time error: ; (but it won't display "one" in the repl, just as it would return #!void) (begin "one" (begin))
;(display (begin "two" (begin))) ; ^- Ill-formed special form: begin
;(pp (lambda() (begin "three" (begin)))) ; ^- Ill-formed special form: begin
; this works, of course, printing "FOUR". (pp (begin "three" (begin "FOUR")))
The same happens in the interpreter and the compiler. (This is on gambc40b14 on Debian x86.)
This construct could be useful in some (rare) cases (see my following mail on macro-debugging).
R5RS doesn't seem to say anything on this. Scheme48 and Mzscheme act the same in all cases. Gauche and SCM don't complain but just always return #<undef> / #<unspecified> from such a construct. bigloo -i only complains in the lambda creation case, otherwise it returns #unspecified.
Thanks, Christian.