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.